メインコンテンツへスキップ
レッスン 6 / 8推定時間: 25

高度なファイル同期

rsync、unison、その他の同期ツールを使った効率的なファイル同期手法を学びます

このレッスンの学習目標

  • rsyncの高度な機能を使いこなす
  • 双方向同期ツールを活用できる
  • 効率的なバックアップ戦略を実装できる
  • ネットワーク経由の同期を安全に行える

rsyncの高度な機能

前のレッスンでrsyncの基本を学びましたが、ここではより高度な機能を探求します。

増分バックアップとハードリンク

CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$

ファイルツリー

/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log

--link-destオプションを使うと、変更されていないファイルは前回のバックアップからハードリンクされるため、 ディスク容量を大幅に節約できます。

# 最初のフルバックアップ
rsync -av source/ backup/full_20240101/

# 増分バックアップ(前回から変更されたファイルのみ)
rsync -av --link-dest=../full_20240101 source/ backup/incremental_20240102/

# さらなる増分バックアップ
rsync -av --link-dest=../incremental_20240102 source/ backup/incremental_20240103/

# ディスク使用量を確認
du -sh backup/*/
ls -li backup/*/docs/file1.txt  # 同じinodeなら成功

スナップショット式バックアップスクリプト

#!/bin/bash
# snapshot_backup.sh

SOURCE="/home/user/documents"
BACKUP_ROOT="/backup/snapshots"
DATE=$(date +%Y%m%d_%H%M%S)
LATEST="$BACKUP_ROOT/latest"
NEW_BACKUP="$BACKUP_ROOT/$DATE"

# 新しいバックアップディレクトリを作成
mkdir -p "$NEW_BACKUP"

# rsyncでバックアップ実行
if [ -d "$LATEST" ]; then
    # 前回のバックアップがあれば、それをベースにする
    rsync -av --delete --link-dest="$LATEST" "$SOURCE/" "$NEW_BACKUP/"
else
    # 初回バックアップ
    rsync -av --delete "$SOURCE/" "$NEW_BACKUP/"
fi

# 成功した場合、latestシンボリックリンクを更新
if [ $? -eq 0 ]; then
    rm -f "$LATEST"
    ln -sf "$DATE" "$LATEST"
    echo "Backup completed successfully: $NEW_BACKUP"
else
    echo "Backup failed"
    exit 1
fi

rsyncの詳細なオプション

CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$

ファイルツリー

/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log
# 詳細な進捗表示
rsync -avh --progress test_sync/src/ test_sync/dest/

# 帯域制限(KB/s)
rsync -av --bwlimit=1000 test_sync/src/ test_sync/dest/

# 部分転送(大きなファイルの中断時に便利)
rsync -avP test_sync/src/ test_sync/dest/

# チェックサム比較(より確実だが遅い)
rsync -avc test_sync/src/ test_sync/dest/

# 圧縮転送
rsync -avz test_sync/src/ user@remote:/path/dest/

# 除外ファイルの指定
echo "*.tmp" > exclude.txt
echo "node_modules/" >> exclude.txt
rsync -av --exclude-from=exclude.txt test_sync/src/ test_sync/dest/

双方向同期:unison

unisonは双方向同期を行うツールで、両方向の変更を検出して同期します。

unisonの基本概念

CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$

ファイルツリー

/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log

unisonの特徴:

  • 双方向同期(両方のディレクトリの変更を検出)
  • 衝突検出(同じファイルが両方で変更された場合)
  • GUI/CUIインターフェース
  • ネットワーク同期対応
# 初期同期
unison sync_test/dir1 sync_test/dir2

# ファイルを両方で変更
echo "modified in dir1" >> sync_test/dir1/shared.txt
echo "new file in dir2" > sync_test/dir2/new.txt

# 再同期(変更を確認して同期)
unison sync_test/dir1 sync_test/dir2

# 自動同期(確認なし)
unison -auto sync_test/dir1 sync_test/dir2

# バッチモード
unison -batch sync_test/dir1 sync_test/dir2

unisonプロファイルの設定

# ~/.unison/myprofile.prf
cat > ~/.unison/myproject.prf << 'EOF'
# ルートディレクトリ
root = /home/user/project
root = ssh://server//home/user/project

# 除外パターン
ignore = Name {*.tmp,*.log}
ignore = Path {.git/*}

# 自動実行
batch = true

# 確認プロンプト
confirm = false

# ファストチェック(修正時刻とサイズで比較)
fastcheck = true
EOF

# プロファイルを使用
unison myproject

ネットワーク同期とセキュリティ

SSH経由の安全な同期

CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$

ファイルツリー

/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log
# SSH鍵の設定(推奨)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/backup_key
ssh-copy-id -i ~/.ssh/backup_key.pub user@backup-server

# SSH鍵を指定したrsync
rsync -av -e "ssh -i ~/.ssh/backup_key" remote_sync/local/ user@backup-server:/backup/

# SSH設定ファイルを使用
# ~/.ssh/config に以下を追加:
# Host backup-server
#   HostName 192.168.1.100
#   User backup
#   IdentityFile ~/.ssh/backup_key
#   Port 2222

# 設定後はシンプルに
rsync -av remote_sync/local/ backup-server:/backup/

# 接続の確認
ssh -o ConnectTimeout=10 backup-server 'echo "Connection successful"'

同期の検証とログ

# 詳細ログ付き同期
rsync -avv --log-file=/var/log/backup.log source/ dest/

# 変更されたファイルのみログ出力
rsync -av --itemize-changes source/ dest/ | tee sync.log

# 統計情報の出力
rsync -av --stats source/ dest/

# ドライラン(実際には実行しない)
rsync -avn --delete source/ dest/

実時間同期(リアルタイム同期)

inotifyを使った自動同期

#!/bin/bash
# realtime_sync.sh

SOURCE="/home/user/workspace"
DEST="user@server:/backup/workspace"
LOG="/var/log/realtime_sync.log"

echo "$(date): Starting realtime sync" >> $LOG

# inotifywaitでファイル変更を監視
inotifywait -m -r -e modify,create,delete,move "$SOURCE" |
while read -r directory events filename; do
    echo "$(date): $events in $directory$filename" >> $LOG
    
    # 少し待ってから同期(連続する変更をまとめる)
    sleep 2
    
    # rsyncで同期実行
    rsync -av --delete "$SOURCE/" "$DEST/" >> $LOG 2>&1
    
    if [ $? -eq 0 ]; then
        echo "$(date): Sync completed successfully" >> $LOG
    else
        echo "$(date): Sync failed" >> $LOG
    fi
done

同期サービスの作成

# /etc/systemd/system/file-sync.service
cat > /etc/systemd/system/file-sync.service << 'EOF'
[Unit]
Description=Real-time File Synchronization
After=network.target

[Service]
Type=simple
User=sync-user
ExecStart=/usr/local/bin/realtime_sync.sh
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

# サービスの有効化
sudo systemctl enable file-sync.service
sudo systemctl start file-sync.service
sudo systemctl status file-sync.service

実践演習

演習1:多世代バックアップシステム

CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$

ファイルツリー

/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log

7日分の日次バックアップと4週分の週次バックアップを保持するシステムを作成してください。

解答例:

#!/bin/bash
# multi_generation_backup.sh

SOURCE="project"
BACKUP_ROOT="backups"
DATE=$(date +%Y%m%d)
WEEK=$(date +%Y_W%U)

# 日次バックアップ
DAILY_DIR="$BACKUP_ROOT/daily/$DATE"
mkdir -p "$DAILY_DIR"

# 前回のバックアップをベースに増分バックアップ
LAST_BACKUP=$(ls -1 "$BACKUP_ROOT/daily/" 2>/dev/null | tail -1)
if [ -n "$LAST_BACKUP" ]; then
    rsync -av --link-dest="../../daily/$LAST_BACKUP" "$SOURCE/" "$DAILY_DIR/"
else
    rsync -av "$SOURCE/" "$DAILY_DIR/"
fi

# 週次バックアップ(日曜日のみ)
if [ $(date +%u) -eq 7 ]; then
    WEEKLY_DIR="$BACKUP_ROOT/weekly/$WEEK"
    mkdir -p "$WEEKLY_DIR"
    rsync -av --link-dest="../../daily/$DATE" "$SOURCE/" "$WEEKLY_DIR/"
fi

# 古いバックアップの削除
find "$BACKUP_ROOT/daily" -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;
find "$BACKUP_ROOT/weekly" -maxdepth 1 -type d -mtime +28 -exec rm -rf {} \;

演習2:衝突解決付き双方向同期

CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$

ファイルツリー

/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log

同じファイルが両方で変更された場合の衝突解決機能を持つ同期スクリプトを作成してください。

解答例:

#!/bin/bash
# conflict_resolution_sync.sh

DIR1="sync/laptop"
DIR2="sync/desktop"
CONFLICT_DIR="sync/conflicts"

mkdir -p "$CONFLICT_DIR"

for file in $(find "$DIR1" -type f); do
    rel_path=${file#$DIR1/}
    file2="$DIR2/$rel_path"
    
    if [ -f "$file2" ]; then
        # 両方にファイルが存在
        if ! cmp -s "$file" "$file2"; then
            # 内容が異なる場合は衝突
            echo "Conflict detected: $rel_path"
            
            # 両方のバージョンを保存
            cp "$file" "$CONFLICT_DIR/${rel_path}.laptop"
            cp "$file2" "$CONFLICT_DIR/${rel_path}.desktop"
            
            # より新しいファイルを採用
            if [ "$file" -nt "$file2" ]; then
                cp "$file" "$file2"
                echo "Used laptop version (newer)"
            else
                cp "$file2" "$file"
                echo "Used desktop version (newer)"
            fi
        fi
    else
        # DIR1にのみ存在
        mkdir -p "$(dirname "$file2")"
        cp "$file" "$file2"
    fi
done

# DIR2にのみ存在するファイルをDIR1にコピー
find "$DIR2" -type f | while read -r file2; do
    rel_path=${file2#$DIR2/}
    file1="$DIR1/$rel_path"
    
    if [ ! -f "$file1" ]; then
        mkdir -p "$(dirname "$file1")"
        cp "$file2" "$file1"
    fi
done

echo "Synchronization completed"

パフォーマンス最適化

rsyncの高速化

# 並列転送(rsyncの代替としてparallelを使用)
find source/ -type f | parallel -j4 'rsync -av {} dest/{}'

# ネットワーク最適化
rsync -av --compress-level=1 source/ dest/  # 軽い圧縮
rsync -av --whole-file source/ dest/        # LAN内では差分無効化

# メモリ使用量の制限
rsync -av --max-size=100M source/ dest/     # 大ファイル除外

監視とアラート

#!/bin/bash
# sync_monitor.sh

SYNC_LOG="/var/log/backup.log"
ERROR_LOG="/var/log/backup_errors.log"
MAIL_RECIPIENT="admin@example.com"

# 同期実行
if ! rsync -av source/ dest/ > "$SYNC_LOG" 2>&1; then
    echo "$(date): Backup failed" >> "$ERROR_LOG"
    
    # エラー通知
    mail -s "Backup Failed" "$MAIL_RECIPIENT" < "$ERROR_LOG"
else
    echo "$(date): Backup successful" >> "$SYNC_LOG"
fi

# 古いログの削除
find /var/log -name "backup*.log" -mtime +30 -delete

トラブルシューティング

よくある問題と解決策

1. rsyncが途中で止まる

# タイムアウト設定
rsync -av --timeout=300 source/ dest/

# 部分転送の続行
rsync -avP source/ dest/

# ネットワーク問題の対処
rsync -av --partial-dir=.rsync-partial source/ dest/

2. 権限の問題

# 数値指定での権限保持
rsync -av --numeric-ids source/ dest/

# 権限を保持しない
rsync -rlptgoD source/ dest/

3. 大量のファイルでメモリ不足

# ファイルリストをディスクに保存
rsync -av --files-from=<(find source -type f) source/ dest/

# バッチ処理
find source -type f -print0 | xargs -0 -n 1000 rsync -av

まとめ

このレッスンでは、高度なファイル同期技術について学びました:

  • rsyncの高度な機能と最適化
  • 双方向同期とコンフリクト解決
  • ネットワーク同期のセキュリティ
  • リアルタイム同期の実装
  • 多世代バックアップ戦略

これらの技術を組み合わせることで、堅牢で効率的なファイル管理システムを構築できます。

💡 次のレッスンでは、ファイル検索の高度な技術について学びます。

さらに学習を続けるには

素晴らしい学習ペースです!次のレッスンに進むには、無料会員登録をお願いします。無料会員では各コース3レッスンまで学習できます。

無料で続きを学ぶ

各コース3レッスンまで学習可能

学習進捗の自動保存

コース修了証明書の発行