第2の人生の構築ログ

自分の好きなことをやりつつ、インカムもしっかりと。FIRA60 (Financial Independence, Retire Around 60) の実現を目指します。SE を生業としていますが、自分でプログラミングしながら自分が欲しいと思うアプリケーションを作ることが楽しみです。旅行と温泉、音楽と読書は欠かすことができません。

rcloneによるクラウドストレージの堅牢なバックアップ運用手法-大容量・多数ファイルの確実な管理

先日、クラウドストレージのバックアップに rclone が便利だったという記事を書きました。

www.morelife.work

その後、運用を行っている中で備忘録として残しておきたい情報がありましたので、こちらに記載しておきます。

ある程度のディレクトリまでは前回の手順で全く問題なかったのですが、より多くのファイルをまとめて扱い、1ファイル当たりのサイズが大きい動画ディレクトリなどでは、 リトライを挟んでも吸収しきれずコピー(ダウンロード)に失敗するケースがぽつぽつ出てきていました。

そこで、コピー(ダウンロード)時のオプション最適化と、失敗が発生した場合のリカバリ手順を整理しました。

  1. コピー(ダウンロード)の実行 (オプションの最適化)
  2. 実行後のチェック
  3. 再実行するファイルの抽出
  4. コピー(ダウンロード)に失敗したファイルに対する再実行

1. コピー(ダウンロード)の実行 (オプションの最適化)

前回の記事では、以下のオプションでクラウドストレージからローカルストレージへのコピーを行っていました。(引数のクラウド側の指定方法などは前回の記事を参照してください。)

$ rclone copy onedrive-priv:Movies/Family \
    /Volumes/MyPassport/Backup/onedrive-202508/Family \
    --progress \
    --fast-list \
    --transfers=16 \
    --checkers=32 \
    --multi-thread-streams=6 \
    --multi-thread-cutoff=32M \
    --buffer-size=16M

これでもいけるのですが、前述のように大量ファイル・大容量ディレクトリではエラーが目立ちました。 そこでオプションを見直し、以下の設定に落ち着いています。--onedrive-chunk-size などは OneDrive 固有なので、他サービスの場合はドキュメントを当たってみてください。

$ rclone copy onedrive-priv:Movies/Violin \
    /Volumes/MyPassport/Backup/onedrive-202508/Violin \
    --progress --fast-list \
    --transfers=8 --checkers=32 \
    --multi-thread-streams=6 --multi-thread-cutoff=32M \
    --onedrive-chunk-size=15Mi \
    --disable-http2 \
    --retries=8 --retries-sleep=30s --low-level-retries=20

主な変更点は以下の通りです。

  • --transfers=8: 同時転送数を少し抑えて回線とCPUの負荷を平均化。
  • --onedrive-chunk-size=15Mi: 大きめのチャンクで転送回数を減らし、断片的な失敗を減少。
  • --disable-http2: HTTP/2 周りのエラーを避けるために HTTP/1.1 に固定。
  • --retries* 系: リトライ回数と間隔を増やして瞬間的な失敗を再取得できるように調整。

2. 実行後のチェック

クラウドストレージとローカルストレージの内容が一致しているかどうかをチェックするには rclone check コマンドを使います。

rclone check onedrive-priv:Movies/Violin \
  /Volumes/MyPassport/Backup/onedrive-202508/Violin \
  --one-way --size-only --progress \
  --combined=${HOME}/tmp/rclone-check-$(date '+%Y-%m-%d-%H-%M-%S').txt

実行後のターミナルにもある程度の情報が出ていますが、combined オプションに指定したファイルにすべてのファイルの詳細が出力されます。 このファイルの内容はコマンドのヘルプでも確認できますが、要点は以下の通りです。

日本語に翻訳します。

|--combined| フラグを使用すると、すべてのファイルパスを含むファイル(または標準出力)を書き出します。
その内容は、記号、スペース、そしてそのファイルに何が起こったかを示すパスが含まれます。これは diff ファイルに似ています。

= path は、そのパスがソースと宛先の両方に存在し、内容が同一であったことを意味します
- path は、そのパスがソースに存在せず、宛先のみに存在していたことを意味します
+ path は、そのパスが宛先に存在せず、ソースのみに存在していたことを意味します
* path は、そのパスがソースと宛先の両方に存在していたが、内容が異なっていたことを意味します
! path は、ソースまたは宛先の読み取りやハッシュ化にエラーが発生したことを意味します

とても有用な情報です。

少しのファイル数であれば目視と手作業でも対応できますが、相当量になると現実的ではありません。ここからは自動化します。

3. 再実行するファイルの抽出

先ほどの combined オプションに指定したファイルを読み込み、コピーに失敗したファイル名だけを抽出します。 以下のスクリプトを使います。

#!/usr/bin/env bash
set -euo pipefail

# 引数チェック
if [[ $# -lt 1 ]]; then
  echo "使い方: $0 path/to/rclone-combined-result.txt"
  exit 1
fi

COMBINED_FILE="$1"

if [[ ! -f "$COMBINED_FILE" ]]; then
  echo "エラー: ファイルが存在しません → $COMBINED_FILE"
  exit 1
fi

# 入力ファイル名とディレクトリを取得
COMBINED_DIR=$(dirname "$COMBINED_FILE")
COMBINED_BASENAME=$(basename "$COMBINED_FILE")
MISSING_LIST="${COMBINED_DIR}/rclone-missing-${COMBINED_BASENAME%.*}.txt"

# 行種別カウント
PLUS_COUNT=$(grep -c '^+ ' "$COMBINED_FILE" || true)
EXCLAM_COUNT=$(grep -c '^! ' "$COMBINED_FILE" || true)

echo "▶️ rclone check 差分ファイルの統計:"
echo "  + missing files:     $PLUS_COUNT"
echo "  ! error files:       $EXCLAM_COUNT"
echo "  = matching files:    $(grep -c '^= ' "$COMBINED_FILE" || true)"
echo

# `+` と `!` 行から対象ファイル名を抽出し、`+` のみ保存
awk '/^[+!][[:space:]]/ { sub(/^[+!][[:space:]]+/, "", $0); print }' "$COMBINED_FILE" \
  | sed 's/\r$//' \
  | grep -v '^!' \
  | sort -u \
  > "$MISSING_LIST"

# 空チェック
if [[ ! -s "$MISSING_LIST" ]]; then
  echo "✅ 差分ファイルなし:再取得不要です。"
  exit 0
fi

echo "💡 再取得対象: $(wc -l < "$MISSING_LIST") 件 → $MISSING_LIST"
head -n 10 "$MISSING_LIST" || true
[[ $(wc -l < "$MISSING_LIST") -gt 10 ]] && echo "... (省略)"

上記のスクリプトを extract_rclone_missing.sh などの名前で保存し、実行権限を付与して実行します。

$ chmod +x extract_rclone_missing.sh
$ ./extract_rclone_missing.sh <combined に指定したファイル名>

結果は MISSING_LIST のファイル名 "${COMBINED_DIR}/rclone-missing-${COMBINED_BASENAME%.*}.txt" に取得に失敗したファイル名だけが出力されます。

4. コピー(ダウンロード)に失敗したファイルに対する再実行

取得に失敗したファイル名のリストを使って、再度 rclone を実行します。

$ rclone copy onedrive-priv:Movies/Violin \
    /Volumes/MyPassport/Backup/onedrive-202508/Violin \
    --files-from /Users/hoge/tmp/missing_violin_file_202508.txt \
    --ignore-existing \
    --progress --fast-list \
    --transfers=8 --checkers=32 \
    --multi-thread-streams=6 --multi-thread-cutoff=32M \
    --onedrive-chunk-size=15Mi --disable-http2 \
    --retries=8 --retries-sleep=30s --low-level-retries=20

最初にたたいた rclone コマンドのオプションとの違いは、files-from オプションでコピー(ダウンロード)対象のファイルを指定しているところです。

前段のスクリプトで生成された MISSING_LIST ファイルのパスをそのまま files-from に渡せば OK です。--ignore-existing を付けているので、既に取得済みのファイルを再度触る心配もありません。

これで取得に失敗したファイル名だけ再コピー(ダウンロード)を実行することになります。

終わりに

この運用でかなりの数、サイズのファイルをクラウドストレージに預けていたのですが、全てのファイルを問題なくローカルストレージにコピーすることができました。 rclone お勧めです。 もし、同じようなことを考えている方がいらっしゃれば、参考になれば幸いです。