コンテンツへスキップ

rsyncの主要オプション(`-avz ‑‑delete`)が何をしているか

サーバーへのファイル転送で rsync -avz --delete という組み合わせをそのままコピー&ペーストして使っている人は多い。動くには動くので深く考えずに使い続けがちだが、それぞれの文字が何を指示しているかを分解して理解しておくと、「なぜこの4文字が必要なのか」「--delete を付けるとどこまで削除されるのか」を自分の判断で説明できるようになる。ここでは主要オプションの中身と、実際のテーマデプロイでの使われ方を整理する。

補足: rsync(remote sync)は、転送元と転送先のファイルを比較し、変更があった部分だけを転送する同期用コマンド。単純なファイルコピーと異なり、差分だけを送るアルゴリズムを内部に持つため、同じファイルを繰り返し転送する用途で強みを発揮する。

オプション早見表

オプション 意味 何をするか
-a archive(アーカイブモード) 再帰的にコピーしつつ、パーミッション・タイムスタンプ・シンボリックリンク・所有者情報などの属性を保つ
-v verbose(詳細出力) 転送したファイル名を一覧表示する
-z compress(圧縮転送) 転送中のデータを圧縮し、ネットワーク経由の転送量を抑える
--delete 削除同期 転送先にあって転送元に存在しないファイルを削除し、転送先を転送元と完全一致させる
-e リモートシェル指定 どのプロトコル・オプションで接続するか(SSH の鍵・ポート等)を指定する

-a は単独オプションではなく複数のフラグの集合

-a は見た目こそ1文字だが、実体は複数のオプションをまとめたショートハンドである。展開すると -rlptgoD に相当し、それぞれ次を意味する。

展開後 意味
-r recursive(ディレクトリを再帰的に処理)
-l シンボリックリンクをリンクのままコピー(実体を複製しない)
-p パーミッションを保持
-t タイムスタンプ(更新日時)を保持
-g グループ情報を保持
-o 所有者情報を保持
-D デバイスファイル・特殊ファイルを保持

このうち特に見落とされがちなのが -t(タイムスタンプ保持)である。rsync は転送要否を判断する際、ファイルサイズと更新日時の組み合わせを使って「前回と変わっていないか」を確認する。-a を使わずタイムスタンプが転送のたびに現在時刻へリセットされる構成にしてしまうと、内容が同じファイルでも毎回「更新日時が違う」と判定されてしまい、差分転送のメリットが薄れて実質フルコピーに近い動作になる。-a を使うことは、単に属性を保つだけでなく、rsync 本来の差分検知の仕組みを正しく機能させるための前提でもある。

--delete はどこまで削除するのか

--delete は、転送先を転送元の状態に完全一致させるためのオプションである。転送元から削除されたファイルが転送先にも反映される一方、指定した転送元・転送先のディレクトリの範囲内でしか効かないという点を正確に理解しておく必要がある。

例えばテーマ用ディレクトリを対象に rsync -avz --delete "$SRC" "$DEST" を実行した場合、--delete が影響するのは $DEST に指定したディレクトリ配下だけであり、そのディレクトリの外にある兄弟ディレクトリ(例えば同じ themes/ 配下にある別のテーマ)には一切影響しない。転送先のパスをどこまで絞り込むかによって --delete の破壊力の範囲が決まる、という理解が実務上は重要になる。

実例 — このプロジェクトのテーマデプロイコマンド

このブログのテーマ(wpmm-blog)をサーバーへ反映する際、実際に次のコマンドを使っている。

SRC=server/wpmm-blog-theme/wpmm-blog/
DEST=layer2024@layer2024.xsrv.jp:wpmm.jp/public_html/blog/wp-content/themes/wpmm-blog/

rsync -avz --delete \
  -e "ssh -i ~/.ssh/layer2024_xserver.key -p 10022 -o BatchMode=yes" \
  "$SRC" "$DEST"

ここでの --deletewp-content/themes/wpmm-blog/ というテーマ専用ディレクトリを対象にしているため、実際に削除されうるのは「ローカルのテーマソースからは既に消えているのに、サーバー側にだけ残っている古いテーマファイル」に限られる。転送先を wp-content/themes/wpmm-blog/ ではなく誤って wp-content/themes/(テーマフォルダ全体)に指定していた場合、他のテーマ(WordPress 標準同梱のテーマなど)まで削除対象に含まれてしまう。ここで対象を「デプロイしたいテーマ専用のディレクトリ」まで絞り込んでおくことが、--delete を安全に使うための実務上のポイントになる。

-e オプションには、SSH 接続に使う鍵ファイル・ポート番号・BatchMode=yes(パスワード入力プロンプトが出た場合に待たずに失敗させる設定)をまとめて指定している。これにより、無人実行のスクリプトの中で予期せず対話的なパスワード入力待ちで止まってしまう事態を避けられる。

転送元パスの末尾スラッシュで結果が変わる

rsync には、転送元パスの末尾にスラッシュ(/)を付けるかどうかでコピー結果が変わるという、よく知られた挙動がある。

  • rsync -av /path/to/src/ /path/to/dest/src ディレクトリの中身dest の直下にコピーされる
  • rsync -av /path/to/src /path/to/dest/src ディレクトリそのものdest/src としてコピーされる

上のテーマデプロイの例では SRC=server/wpmm-blog-theme/wpmm-blog/ のように末尾スラッシュを付けているため、「wpmm-blog/ の中身」が転送先の wpmm-blog/ 直下に展開される構成になっている。末尾スラッシュの有無を意識せずにコマンドを組み立てると、想定していた階層とは1段ずれた場所にファイルが配置される事故につながりやすい。

まとめ

オプション 一言で言うと
-a 属性を保ったまま再帰コピーする(-rlptgoD の集合)
-v 何が転送されたかを画面に出す
-z 転送データを圧縮して帯域を節約する
--delete 転送先を転送元に完全一致させる(対象範囲の絞り込みが安全に使う鍵)
-e 接続方法(SSH の鍵・ポート等)を指定する

-avz --delete はよく見かける定番の組み合わせだが、それぞれの文字が独立した役割を持っている。特に --delete は転送先のパスをどこまで絞るかで影響範囲が変わるため、対象ディレクトリを意識して使うことが、意図しないファイル削除を避ける上での基本になる。