【Linux】rsyncコマンドの使い方完全ガイド|主要オプション一覧と末尾スラッシュの注意点

コマンドリファレンス実務レシピ

こんにちは、 **Bash玄(ばっしゅげん)** です。

Linuxサーバーの運用管理やWebサイトのデプロイ、定期バックアップ作業において、 `cp` コマンドや `scp` コマンドを使っていて **「毎回全ファイルを転送しているため時間がかかりすぎる」「通信が途中で切断されて最初からやり直しになった」「意図しない階層にコピーされて本番サイトが404エラーになった」** という痛い失敗を経験したことはありませんか?

データ容量が数ギガバイトから数十ギガバイトに膨らんだ環境において、毎回すべてのファイルをコピーするのはディスクI/Oとネットワーク帯域の大いなる無駄遣いです。こうした現場のファイル転送・バックアップ課題をスマートかつ安全に解決する決定版ツールが、Linux標準の同期ユーティリティ **`rsync`(リモートシンク)コマンド** です。

`rsync` は、転送元と転送先の差分データのみを高速転送する仕組みを備えており、属性(パーミッション・所有者・更新日時)の保持、SSH暗号化通信、中断再開、完全ミラーリングまで自在にこなします。しかしその一方で、 **「末尾スラッシュの有無でディレクトリ階層が激変する」「`–delete` で本番データを消去してしまう」** といった落とし穴も潜んでいます。

本記事では、 `rsync` コマンドの基礎知識から頻出オプション一覧、初心者が必ずハマる末尾スラッシュ問題の図解、SSH経由のリモート同期、実務で役立つ実践シェルスクリプト、そしてトラブルシューティングまで現役インフラエンジニア目線で徹底解説します!

  1. rsyncコマンドとは?cpコマンドとの違いと選ばれる3つの理由
    1. 1. 変更された差分データのみを高速転送(時間とネットワークの節約)
    2. 2. SSH経由による安全なリモートサーバー間ファイル同期
    3. 3. 転送中断時の再開(レジューム)や進捗状況の可視化
  2. 【最速コピペ】これだけ覚えれば動く!鉄板コマンド3選
    1. 1. ローカルディレクトリの同期(rsync -avh src/ dst/)
    2. 2. 実行前のシミュレーションテスト(–dry-run)
    3. 3. SSH経由でリモートサーバーへ転送(rsync -avz -e ssh)
  3. 【最重要】末尾スラッシュ「/」の有無による挙動の違い【図解】
    1. スラッシュあり(src/):ディレクトリの「中身」だけを転送
    2. スラッシュなし(src):ディレクトリ「そのもの」を転送
    3. ASCIIツリーで見る転送結果の決定的な差
  4. rsync主要オプション完全一覧早見表
    1. -a(アーカイブモード:パーミッション・所有者・タイムスタンプ・リンク・再帰を完全保持)
    2. -v, -h(詳細ログ表示とファイルサイズ・単位の人間向け可読化)
    3. -z(データ圧縮転送:回線帯域の節約)
    4. -P / –partial –progress(進捗バー表示と中断再開機能の有効化)
    5. -n / –dry-run(本番前の必須テスト実行)
    6. –delete(完全同期ミラーリングの挙動とデータ消失を防ぐ注意点)
    7. –exclude / –exclude-from(.git や node_modules 等の特定除外指定)
  5. SSH経由でリモートサーバーとファイル同期・転送する方法
    1. 基本的なリモート転送構文(ローカル→リモート / リモート→ローカル)
    2. SSHポート番号(22番以外)や秘密鍵を指定する方法(-e ‘ssh -p ポート -i 鍵’)
  6. 実務で使える実践活用レシピ
    1. レシピ1: Webサイト公開・デプロイ時の完全ミラーリング
    2. レシピ2: 帯域制限(–bwlimit)をかけて業務回線の圧迫を防ぐバックアップ
    3. レシピ3: シェルスクリプトとcronを組み合わせた自動バックアップ
  7. よくある失敗・落とし穴とトラブルシューティング
    1. Permission denied(パーミッションエラー)の回避(–rsync-path=’sudo rsync’)
    2. –delete で誤って本番データを消去しないための「2段階実行ルール」
  8. まとめ & 関連コマンド(cp, scp, tar との使い分け基準)
  9. 関連記事

rsyncコマンドとは?cpコマンドとの違いと選ばれる3つの理由

`rsync` (Remote Sync)は、同一マシン内のローカルディレクトリ間、あるいはネットワークを経由したリモートサーバー間で、ファイルやディレクトリを高速かつ安全に同期(シンクロナイズ)するためのコマンドラインユーティリティです。

Linuxの標準的なファイルコピーコマンドである `cp` や、リモート転送コマンドである `scp` と比較して、なぜ `rsync` が世界中のインフラ現場でデファクトスタンダードとして選ばれ続けているのか、その **3つの決定的な理由** を解説します。

1. 変更された差分データのみを高速転送(時間とネットワークの節約)

`cp` コマンドや `scp` コマンドは、コピー先に同名ファイルが存在していても、あるいは1バイト修正されただけであっても、 **ファイル全体を丸ごと再送** します。そのため、10GBのデータベースバックアップや大容量ログファイルの同期を行う場合、毎回10GB分のディスク読み書きとネットワーク通信が発生してしまいます。

対して `rsync` は、独自の **「差分転送アルゴリズム(ローリングハッシュ・ブロック比較)」** を備えています。ファイルをブロック単位(数KB〜数十KB)に分割してハッシュ値を比較し、 **「追加・変更のあったブロックのみ」** を抽出して転送します。初回転送こそ全量コピーになりますが、2回目以降の定期同期では通信量と所要時間を **数十分の1から数百分の1にまで大幅圧縮** できます。

2. SSH経由による安全なリモートサーバー間ファイル同期

`rsync` は、デフォルトの通信プロトコルとして **SSH(Secure Shell)** を標準採用しています。専用のデーモンプロセス(rsyncデーモン)を常駐させる必要がなく、既存のSSHポート(22番)や鍵認証の仕組みをそのまま利用して、強固に暗号化された安全なファイル同期を実現できます。

リモートサーバー間での機密設定ファイルやデータベースダンプの転送も、平文がネットワーク上に流れる心配がなく、インフラセキュリティ要件をクリアできます。

3. 転送中断時の再開(レジューム)や進捗状況の可視化

ネットワーク経由で大容量アーカイブを転送している最中に通信断やタイムアウトが発生した場合、 `scp` や通常のコピーでは最初からやり直しを余儀なくされます。

`rsync` では `-P`(`–partial –progress`)オプションを指定することで、 **転送途中の不完全なファイルを破棄せず保持し、次回実行時に中断した箇所から再開(レジューム)** することが可能です。また、現在の転送速度、残り予想時間、進捗率パーセンテージがリアルタイムにターミナルへ表示されるため、運用オペレーターが状況を正確に把握できます。

機能・特徴rsynccpscptar(パイプ連携)
**差分転送** ○(高速ブロック転送)×(全量コピー)×(全量コピー)×(全量転送)
**リモート転送** ○(SSH標準統合)×(ローカル限定)○(SSH通信)△(SSHパイプ経由)
**属性・権限の完全保持** ○(`-a` で完全同期)○(`-a` 指定時)△(一部属性欠落あり)○(アーカイブ保持)
**中断再開(レジューム)** ○(`-P` オプション)×(最初から)×(最初から)×(最初から)
**不要ファイルの自動削除** ○(`–delete` ミラー)×(削除不可)×(削除不可)×(削除不可)
**現場での主な位置づけ** 定常バックアップ・デプロイローカル単発ファイル退避単発の緊急ファイル送受信一括アーカイブ・圧縮保存

【最速コピペ】これだけ覚えれば動く!鉄板コマンド3選

「細かいオプションを覚える前に、まずは現場で安全に動くコマンドを今すぐ使いたい!」という方のために、実務の9割をカバーできる **鉄板コマンド3選** をまとめました。

1. ローカルディレクトリの同期(rsync -avh src/ dst/)

同一サーバー内の別ディレクトリやマウントされた外付けストレージへ、ディレクトリの中身を高速かつ属性を保ったままコピーする基本構文です。

# ローカルディレクトリの同期(パーミッション保持・詳細ログ・可読単位)
rsync -avh /var/www/html/ /backup/html/
  • **`-a`(アーカイブ)** :パーミッション、所有者、更新日時、シンボリックリンク構造を完全保持し再帰コピー
  • **`-v`(詳細表示)** :転送されたファイル名の一覧を標準出力に表示
  • **`-h`(可読化)** :ファイルサイズを 1024K ではなく 1.0M のように人間が読みやすい形式で表示
  • **`/var/www/html/` の末尾スラッシュ** : `html` ディレクトリの **「中身だけ」** を `/backup/html/` 直下へ同期

2. 実行前のシミュレーションテスト(–dry-run)

本番環境でファイルコピーや同期を実行する前に、 **「実際にファイル書き換えや削除を行わず、何が起きるかだけを画面に出力する」** テスト実行(ドライラン)を行います。

# 本番前のテスト実行(ドライラン:実際の変更は一切行われない)
rsync -avhn /var/www/html/ /backup/html/

# --dry-run ロングオプションでの指定(意味は同一)
rsync -avh --dry-run /var/www/html/ /backup/html/

💡 【玄人ワンポイント】
実務において、特に後述する `–delete` オプションを併用する際は、 **「まず -n を付けて実行し、画面出力を確認してから -n を外して本番実行する」** ことが、インフラエンジニアの鉄則(プロトコル)です。

3. SSH経由でリモートサーバーへ転送(rsync -avz -e ssh)

ローカルサーバーのデータを、リモートの別サーバーへSSH暗号化通信経由で安全に転送する王道コマンドです。

# SSH経由でリモートサーバーへ同期(データ圧縮転送)
rsync -avzh -e ssh /var/www/html/ deploy_user@remote-server.example.com:/var/www/html/
  • **`-z`(圧縮転送)** :転送データをリアルタイムに可逆圧縮し、ネットワーク通信量を大幅削減
  • **`-e ssh`** :リモート接続シェルとしてSSHを明示的に指定

【最重要】末尾スラッシュ「/」の有無による挙動の違い【図解】

`rsync` コマンドを扱うエンジニアが最も頻繁に引っかかり、重大インシデント(Webサイトの404エラーや階層二重化)を引き起こす最大の要因が **「コピー元(SOURCE)パスの末尾スラッシュ(`/`)の有無」** です。

「スラッシュが1文字あるかないか」だけで、同期対象が **ディレクトリの『中身』なのか、ディレクトリ『そのもの』なのか** が根本から変化します。

スラッシュあり(src/):ディレクトリの「中身」だけを転送

コピー元の末尾にスラッシュを付けた場合(例: `src/`)、 `rsync` は **「`src` フォルダの内側にあるファイルやサブフォルダ群(中身)」** を転送対象として認識します。

同期先ディレクトリの直下に中身がそのままフラットに展開されるため、Webデプロイや完全ミラーリングではこの形式が多用されます。

スラッシュなし(src):ディレクトリ「そのもの」を転送

コピー元の末尾にスラッシュを付けない場合(例: `src`)、 `rsync` は **「`src` というディレクトリコンテナそのもの」** を転送対象として認識します。

その結果、同期先ディレクトリの中に新しく `src` フォルダが作成され、その配下にファイル群が格納されます。

ASCIIツリーで見る転送結果の決定的な差

実際のファイルツリーを用いて、スラッシュあり・なしで同期先の結果がどう異なるかを視覚的に確認してみましょう。

【同期元のディレクトリ構造】
/var/www/src/
├── index.html
├── style.css
└── images/
    └── logo.png

======================================================================
パターンA:末尾スラッシュ【あり】(中身だけを同期先に展開)
======================================================================
$ rsync -av /var/www/src/ /backup/dest/

【同期先 /backup/dest/ の結果】
/backup/dest/
├── index.html
├── style.css
└── images/
    └── logo.png
※ srcディレクトリは作られず、src内のファイル群がdest直下に配置される。

======================================================================
パターンB:末尾スラッシュ【なし】(ディレクトリごと同期先に格納)
======================================================================
$ rsync -av /var/www/src /backup/dest/

【同期先 /backup/dest/ の結果(二重階層の発生)】
/backup/dest/
└── src/ ← ★ destの中にsrcディレクトリが丸ごと生成される!
    ├── index.html
    ├── style.css
    └── images/
        └── logo.png

⚠️ 【警告】データ消失事故への注意
Webサーバーの公開フォルダ(ドキュメントルート)にパターンB(スラッシュなし)を実行してしまうと、本来 `/backup/dest/index.html` にあるべきファイルが `/backup/dest/src/index.html` に配置され、ブラウザからアクセスした際に **404 Not Found** が発生してサービス停止事故につながります。

指定パターンコマンド記法同期先での結果実務での覚え方
**末尾スラッシュ【あり】** `rsync -a src/ dst/``dst/file.txt`「フォルダの **中身全部** をdstに撒く」
**末尾スラッシュ【なし】** `rsync -a src dst/``dst/src/file.txt`「フォルダ **そのもの** をdstに入れる」

💡 【玄人ワンポイント】
なお、コピー先(DEST)側の末尾スラッシュ(`dst/` vs `dst`)については、既存のディレクトリが存在する場合は動作に差はありません。しかし、 **「ディレクトリに対して転送している」という意図を明確にし、万が一DESTが存在しない場合に単一ファイル名として誤作成されるのを防ぐため、コピー先にも必ず末尾スラッシュを付ける** のが安全な作法です。

rsync主要オプション完全一覧早見表

`rsync` には多種多様なオプションが用意されています。実務で頻繁に利用される重要オプションを一覧表に整理しました。

オプションロング名機能概要実務での用途・併用例
**`-a`** `–archive`アーカイブモード(属性保持・再帰)実務必須。`-rlptgoD` の一括ショートカット
**`-v`** `–verbose`詳細ログの出力転送ファイル名やサマリーを出力
**`-h`** `–human-readable`容量単位を人間可読化(K, M, G)ログや進捗のサイズを視認しやすくする
**`-z`** `–compress`転送データのリアルタイム圧縮SSHリモート転送時の回線帯域・時間を節約
**`-P`** `–partial –progress`進捗バー表示 + 中断再開機能巨大ファイル転送や不安定な回線での同期
**`-n`** `–dry-run`シミュレーション(ドライラン)実行ファイル書き換えを行わず事前検証
**`–delete`** 完全ミラーリング(削除同期)転送元に存在しない転送先ファイルを削除
**`–exclude`** 特定パターン・ファイルの除外`.git` やキャッシュ・ログファイルを除外
**`–exclude-from`** 除外リストファイルの一括読み込み除外対象が多い場合の外部ファイル指定
**`-e`** `–rsh`リモート接続コマンドの指定SSHポート変更(`-p 2222`)や秘密鍵指定
**`–bwlimit`** 転送帯域幅の制限(KB/s)本番業務回線の圧迫防止(例: `–bwlimit=5000`)
**`-u`** `–update`更新ファイルのみ転送転送先の方が新しい場合は上書きスキップ
**`-c`** `–checksum`チェックサムによる厳密差分判定タイムスタンプが狂っている場合の確実な同期
**`–stats`** 転送統計サマリーの出力スクリプトログに転送バイト数や速度を記録
**`–remove-source-files`** 転送成功後に転送元ファイルを削除ファイル移動(mv)処理の代替

-a(アーカイブモード:パーミッション・所有者・タイムスタンプ・リンク・再帰を完全保持)

`-a` (`–archive`)は、実務で `rsync` を叩く際に **ほぼ100%付与すべき最も重要なフラグ** です。以下の7つのオプションを同時に有効化する強力な合成オプションとなっています。

  • **`-r`(`–recursive`)** :サブディレクトリを再帰的に走査して配下の全ファイルを同期
  • **`-l`(`–links`)** :シンボリックリンクを実体コピーせず、リンク属性のまま複製
  • **`-p`(`–perms`)** :元のパーミッション(実行権限 755 や 644 など)を完全に維持
  • **`-t`(`–times`)** :タイムスタンプ(更新日時 mtime)を完全保持(次回の差分判定に不可欠)
  • **`-g`(`–group`)** :所有グループ情報を保持
  • **`-o`(`–owner`)** :所有ユーザー情報を保持(※root実行時のみ有効)
  • **`-D`(`–devices –specials`)** :ブロックデバイスや特殊キャラクタデバイスを保持

`-a` を付けずに実行すると、更新日時が「同期を実行した現在時刻」に書き換わってしまい、次回の `rsync` 実行時に全ファイルが更新されたと判定されて差分転送が機能しなくなる原因となります。

-v, -h(詳細ログ表示とファイルサイズ・単位の人間向け可読化)

`-v` は転送されたファイル名を出力し、 `-h` はバイト単位の数値を `1.5M` や `2.3G` のように単位付きで表示します。この2つを合わせて `-avh` とする組み合わせが基本形です。

-z(データ圧縮転送:回線帯域の節約)

ネットワーク転送時にデータを可逆圧縮しながら送受信します。ソースコード、HTML/CSS/JS、ログファイル、SQLダンプなどのテキストデータに対して絶大な効果を発揮し、転送時間を大幅に短縮できます。

💡 【玄人ワンポイント】
ただし、すでに圧縮されている画像ファイル(JPEG, PNG, WebP)や動画(MP4)、圧縮アーカイブ(`.tar.gz`, `.zip`)を大量に転送する場合は、CPUの圧縮処理オーバーヘッドによって逆に速度が低下することがあります。同一LAN内やギガビット回線での大容量バイナリ転送では、あえて `-z` を外すチューニングも有効です。

-P / –partial –progress(進捗バー表示と中断再開機能の有効化)

`-P` は `–partial` と `–progress` をまとめたショートカットです。

  • **`–progress`** :ファイルごとの転送率、転送速度、残り時間をリアルタイムに表示
  • **`–partial`** :ネットワーク切断等で転送が失敗した際、受信側の途中まで書き込まれたテンポラリファイルを消さずに残し、次回実行時に続きからレジューム転送を可能にする
# 巨大ファイル(DBダンプ)をレジューム可能かつ進捗表示付きで転送
rsync -avhP /backup/dump_large.sql.gz user@backup-server:/storage/db/

-n / –dry-run(本番前の必須テスト実行)

`-n` を付与することで、ファイルシステムの変更を一切行わずに「何がコピーされ、何が削除されるか」のログ出力だけをシミュレーションできます。破壊的操作を伴うコマンドでは、必ず最初に実行する習慣を身につけましょう。

–delete(完全同期ミラーリングの挙動とデータ消失を防ぐ注意点)

通常、 `rsync` は転送元にあるファイルを転送先へコピー・上書きしますが、 **「転送元ですでに削除されたファイル」は転送先にはそのまま残ります** 。転送元と転送先を完全に一致させたい(完全ミラーリング)場合に指定するのが `–delete` オプションです。

⚠️ 【警告】データ消失事故への注意
`–delete` は極めて危険な破壊的オプションです。もしコピー元の指定パスを誤ったり、末尾スラッシュを間違えたりした場合、 **転送先ディレクトリの全データが一瞬で消去(ロスト)** します。
【安全運用の絶対ルール】
1. 必ず事前に `-n`(`–dry-run`)を付与して実行する
2. ログ内に `*deleting …` と表示されるファイル一覧を目視確認する
3. 削除対象に問題がないことを確信してから `-n` を外して本番実行する

–exclude / –exclude-from(.git や node_modules 等の特定除外指定)

デプロイやバックアップの際、不要な管理ファイルや一時ファイルを除外するために `–exclude` を使用します。

# 個別パターンの除外
rsync -avh --delete 
    --exclude=".git/" 
    --exclude="node_modules/" 
    --exclude="*.log" 
    --exclude=".env" 
    /var/www/app/ /backup/app/

除外パターンが多い場合は、テキストファイルに1行ずつ記述して `–exclude-from` で一括指定すると管理が容易です。

# 除外リストファイル(例: .rsyncignore)の中身
.git/
node_modules/
storage/logs/*.log
*.tmp
.env

# リストファイルを利用した同期実行
rsync -avh --delete --exclude-from='.rsyncignore' /var/www/app/ /backup/app/

SSH経由でリモートサーバーとファイル同期・転送する方法

実務において最も需要が高いのが、本番サーバーからバックアップサーバーへ、またはCI/CD環境からWebサーバーへSSH経由で同期するケースです。

基本的なリモート転送構文(ローカル→リモート / リモート→ローカル)

リモートサーバーを指定する場合、 `ユーザー名@ホスト名:ディレクトリパス` の形式で引数を記述します。

# 【プッシュ型】ローカルからリモートサーバーへアップロード同期
rsync -avz -e ssh /local/data/ user@remote.example.com:/remote/data/

# 【プル型】リモートサーバーからローカルマシンへダウンロード同期
rsync -avz -e ssh user@remote.example.com:/remote/data/ /local/data/

SSHポート番号(22番以外)や秘密鍵を指定する方法(-e ‘ssh -p ポート -i 鍵’)

セキュリティ強化のためにSSHの待受ポートをデフォルトの22番から変更している環境や、特定の秘密鍵ファイルを使用する場合は、 `-e` オプションにクォートで囲んだSSHコマンドを渡します。

# ポート番号 2222番、特定の秘密鍵 ~/.ssh/id_ed25519 を指定して転送
rsync -avz -e "ssh -p 2222 -i ~/.ssh/id_ed25519" /var/www/html/ user@remote.example.com:/var/www/html/

毎回長い `-e` オプションを記述するのが手間の場合は、 `~/.ssh/config` にホスト設定を記述しておくことで、コマンドを大幅にシンプル化できます。

# ~/.ssh/config の設定例
Host web-prod
    HostName 192.168.11.50
    Port 2222
    User deployer
    IdentityFile ~/.ssh/id_ed25519

# 設定後のスマートなrsync実行(-e オプションの記述が不要!)
rsync -avz /var/www/html/ web-prod:/var/www/html/

詳しいSSH接続設定のまとめ方については、当サイトの解説記事 「SSH configの書き方|~/.ssh/configで接続設定をまとめる方法」 および 「【Linux】SSH 鍵認証の設定手順まとめ」 もあわせてご参照ください。

実務で使える実践活用レシピ

インフラ運用現場で実際に導入されている、即戦力の活用レシピを3つ紹介します。

レシピ1: Webサイト公開・デプロイ時の完全ミラーリング

Gitで管理されたプロジェクトからビルド成果物を本番Webサーバーへ同期し、不要になった古いアセットファイルを自動削除するデプロイ用コマンドです。

# Webデプロイ:差分転送+不要ファイル削除+特定ファイル除外
rsync -avzh --delete 
    --exclude=".git/" 
    --exclude=".env" 
    --exclude="storage/framework/cache/*" 
    --exclude="storage/logs/*.log" 
    /home/deploy/build/web/ prod-web:/var/www/html/

レシピ2: 帯域制限(–bwlimit)をかけて業務回線の圧迫を防ぐバックアップ

昼間の業務稼働中に大容量バックアップやデータ移行を行う場合、ネットワーク帯域を使い切ってしまうと本番サービスや社内ネットワークに遅延が発生します。 `–bwlimit` を指定して上限帯域をコントロールしましょう。

# 転送速度の上限を 5,000 KB/s(約 5 MB/s = 40 Mbps)に制限して同期
rsync -avzh --bwlimit=5000 /data/big_archives/ backup-server:/storage/archives/

レシピ3: シェルスクリプトとcronを組み合わせた自動バックアップ

深夜に定期実行される自動バックアップスクリプトの本格的な実装例です。二重起動防止(`flock`)、厳格なエラーハンドリング(`set -euo pipefail`)、日付ごとのログ出力、エラー時の検知を備えています。

#!/bin/bash
# ==============================================================================
# バックアップ自動実行スクリプト
# ==============================================================================
set -euo pipefail

# --- 基本設定 ---
readonly BACKUP_SRC="/var/www/html/"
readonly BACKUP_DEST="backup_user@backup-host.internal:/storage/daily_backup/"
readonly LOG_DIR="/var/log/backup"
readonly LOG_FILE="${LOG_DIR}/rsync_$(date +%Y%m%d).log"
readonly LOCK_FILE="/var/run/rsync_backup.lock"
readonly SSH_KEY="/root/.ssh/id_backup_ed25519"

# ログディレクトリの作成
mkdir -p "$LOG_DIR"

# --- 二重起動防止(排他ロック) ---
exec 200>"$LOCK_FILE"
if ! flock -n 200; then
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SKIP] 前回のバックアップ処理がまだ実行中です。" >> "$LOG_FILE"
    exit 1
fi

echo "=================================================================" >> "$LOG_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [START] バックアップ同期処理を開始します。" >> "$LOG_FILE"

# --- rsync 実行 ---
# -a: アーカイブ保持, -v: 詳細ログ, -z: 圧縮, --delete: 完全同期
# -e: 鍵指定SSH, --bwlimit: 帯域制限
if rsync -avz --delete --bwlimit=10000 --exclude="*.tmp" --exclude="cache/*" --exclude=".git/" -e "ssh -i ${SSH_KEY} -o StrictHostKeyChecking=accept-new" "${BACKUP_SRC}" "${BACKUP_DEST}" >> "$LOG_FILE" 2>&1; then

    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] バックアップが正常終了しました。" >> "$LOG_FILE"
    EXIT_STATUS=0
else
    EXIT_STATUS=$?
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] バックアップが異常終了しました (Exit Code: ${EXIT_STATUS})" >> "$LOG_FILE"
    # ※ 必要に応じてアラート通知(Slack / メール等)をここに実装
fi

echo "=================================================================" >> "$LOG_FILE"
exit "$EXIT_STATUS"

このスクリプトを `crontab -e` で毎朝4時に実行する設定例:

# 毎日午前4時00分に自動バックアップを実行
0 4 * * * /usr/local/bin/backup_rsync.sh > /dev/null 2>&1

cronの書式やデバッグ手法の詳細については、 「cronの設定方法|crontabの書き方・オプション・実行例を解説」「【crontab書き方早見表】時間指定・曜日・実行間隔の構文と動かない時のデバッグ完全ガイド」 をご覧ください。

よくある失敗・落とし穴とトラブルシューティング

実務で遭遇しやすい代表的なエラーと、その確実な回避策を解説します。

Permission denied(パーミッションエラー)の回避(–rsync-path=’sudo rsync’)

リモートサーバーへ転送する際、転送先ディレクトリの所有者が `root` や `www-data` など別ユーザーに設定されていると、一般ユーザーでSSHログインした際に **`Permission denied (13)`** エラーが発生します。

リモート側でrootパスワードなしのsudo権限(NOPASSWD)が許可されている場合、 `–rsync-path` オプションを使って **リモート側でsudo権限付きのrsyncプロセスを起動させる** のが現場の定番テクニックです。

# リモート側で sudo rsync を実行してパーミッション不足を回避
rsync -avz --rsync-path="sudo rsync" /local/configs/ deployer@remote.example.com:/etc/nginx/

権限問題の切り分け方法については、当サイトの解説記事 「Permission deniedの原因と直し方|6つの切り分け手順」 にて体系的にまとめています。

–delete で誤って本番データを消去しないための「2段階実行ルール」

前述のとおり、 `–delete` オプションは誤操作によって取り返しのつかないデータ消失を引き起こすリスクがあります。現場では必ず以下の **「2段階実行ルール」** を徹底してください。

  • **ステップ1:ドライラン確認**
    `rsync -avh -n –delete src/ dst/` を実行し、出力ログに削除されるファイル(`*deleting …`)がリストアップされているか確認する。
  • **ステップ2:安全なバックアップ退避(世代バックアップの併用)**
    削除されるファイルを即座に破棄せず、別フォルダへ退避させる `–backup` および `–backup-dir` オプションを併用する。
# 削除・上書きされるファイルを消さずに /backup/deleted/ 配下へ退避させる
rsync -avh --delete 
    --backup --backup-dir=/backup/deleted_$(date +%Y%m%d)/ 
    /var/www/html/ /backup/html/

この設定を行っておけば、万が一誤って重要なファイルを転送元で消してしまっても、退避ディレクトリから簡単に復元(ロールバック)することができます。

まとめ & 関連コマンド(cp, scp, tar との使い分け基準)

本記事では、Linuxにおけるファイル同期とバックアップの最強ユーティリティ **`rsync` コマンド** について、基本構文から重要オプション、末尾スラッシュの仕様、実践シェルスクリプトまで詳しく解説しました。

最後に、実務で迷わないための要点とコマンド使い分け基準をおさらいしておきましょう。

  • **「迷ったら -avz」が鉄則** :パーミッション・属性完全保持(`-a`)、詳細ログ(`-v`)、通信圧縮(`-z`)の組み合わせで安全かつ最速の同期を実現。
  • **末尾スラッシュ「/」を絶対に見落とさない** :中身だけを展開したいときは `src/` 、ディレクトリごと格納したいときは `src` 。
  • **`–delete` 実行時は必ず `-n`(`–dry-run`)を挟む** :本番事故を防ぐため、シミュレーション確認または `–backup-dir` 退避を徹底する。

日常的なコマンドの使い分けとしては、 **「同一ホスト内の単発退避には `cp -a` 」「複数ファイルの保管・配布には `tar` 」「サーバー間転送やディレクトリ定期同期にはすべて `rsync` 」** を選択するのが最も安全で生産性の高い運用スタイルです。

他の主要コマンドの使い方やシェルスクリプトの自動化テクニックについては、以下の関連ガイドもぜひブックマークして活用してください!

Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする

コメント