こんにちは、かつコーチです。
L20でSSHの基本を解説しましたが、SSHが使えるようになると次にやりたくなるのがファイルの転送です。
「ローカルのファイルをサーバーにアップロードしたい」「サーバーのログをローカルに落として確認したい」。
そんなときに使うのがscpとrsyncです。
この記事では、それぞれの使い方と、どちらを選ぶべきかの判断軸を解説します。
検証環境はUbuntu 26.04 LTSです。
ファイル転送コマンドとは?
scpとrsyncの定義
scp(Secure Copy)とは、SSHの暗号化通信を使って、ローカルとリモートサーバーの間でファイルをコピーするコマンドです。
rsyncとは、ファイルの差分だけを検出して転送する、より高機能な同期用コマンドです。
どちらもSSH経由で安全に転送できる点は共通していますが、得意な用途が異なります。
なぜファイル転送の仕組みが必要なのか
サーバー運用では、次のような場面でファイル転送が欠かせません。
- ローカルで開発したアプリケーションのコードをサーバーにデプロイする
- サーバーの設定ファイルをバックアップとしてローカルに保存する
- 障害調査のために、サーバー上のログファイルをローカルへ持ち帰る
GUIのファイル転送ソフト(FTPクライアントなど)を使う方法もありますが、CUI操作に慣れると、コマンド1行で完結するscpやrsyncの方が圧倒的に効率的です。
scpの基本の書き方
手順1:ローカルからサーバーへアップロードする
# ローカルのファイルをサーバーの/home/user/配下にコピー
$ scp ./app.zip user@203.0.113.10:/home/user/
app.zip 100% 12MB 8.2MB/s 00:01
「コピー元」「コピー先」の順に指定するのは、通常のcpコマンドと同じ考え方です。
サーバー側のパスはユーザー名@ホスト名:パスの形式で表します。
手順2:サーバーからローカルへダウンロードする
# サーバーのログをローカルにコピー
$ scp user@203.0.113.10:/var/log/nginx/error.log ./error.log
error.log 100% 340KB 5.1MB/s 00:00
コピー元とコピー先を逆にするだけで、ダウンロードにも同じコマンドが使えます。
手順3:ディレクトリごとコピーする
ディレクトリを丸ごとコピーしたい場合は-rオプション(再帰的コピー)を付けます。
$ scp -r ./project user@203.0.113.10:/home/user/project
手順4:configのエイリアスを使って簡略化する
L20で設定した~/.ssh/configのホスト名(エイリアス)は、scpでもそのまま使えます。
$ scp ./app.zip web01:/home/user/
rsyncの基本の書き方
手順1:基本的な同期を実行する
# ローカルのディレクトリをサーバーに同期する
$ rsync -avz ./project/ user@203.0.113.10:/home/user/project/
sending incremental file list
./
index.html
style.css
sent 2,048 bytes received 41 bytes 4,178.00 bytes/sec
total size is 1,890 speedup is 0.90
代表的なオプションの意味は次の通りです。
| オプション | 意味 |
|---|---|
-a | 権限・タイムスタンプなどを保持したまま同期する(archiveモード) |
-v | 転送状況を詳しく表示する(verbose) |
-z | 転送中にデータを圧縮する |
手順2:差分だけを転送する
rsyncの最大の特徴は、2回目以降の実行で変更のあったファイルだけを転送してくれる点です。
# 1回目:全ファイルを転送
$ rsync -avz ./project/ user@203.0.113.10:/home/user/project/
sent 2,048 bytes ...
# ファイルを1つだけ編集後、2回目を実行
$ rsync -avz ./project/ user@203.0.113.10:/home/user/project/
sending incremental file list
index.html
sent 412 bytes received 35 bytes 894.00 bytes/sec
2回目は変更したindex.htmlだけが転送され、送信データ量が大幅に減っていることが分かります。
大量のファイルを扱うデプロイ作業では、この差分転送が時間短縮に直結します。
手順3:削除も同期する
サーバー側にしかない不要なファイルまで揃えたい場合は--deleteオプションを付けます。
# ローカルにないファイルはサーバー側からも削除する
$ rsync -avz --delete ./project/ user@203.0.113.10:/home/user/project/
--deleteは意図せずサーバー側のファイルを消してしまう危険があるため、実行前に--dry-run(試験実行)で確認する習慣をつけてください。
# 実際には転送・削除せず、結果だけを確認する
$ rsync -avz --delete --dry-run ./project/ user@203.0.113.10:/home/user/project/
scpとrsyncの比較・選び方
コマンド対応表
| 用途 | scp | rsync |
|---|---|---|
| 単発の1ファイルコピー | ◎ シンプルで手軽 | ○ オプションがやや多い |
| 大量ファイル・大容量ディレクトリの同期 | △ 毎回全体を転送する | ◎ 差分だけ転送するので高速 |
| 定期的なバックアップ・デプロイ | △ 差分転送に非対応 | ◎ 差分転送・削除同期に対応 |
| コマンドの覚えやすさ | ◎ cpと同じ感覚 | △ オプションを覚える必要がある |
どちらを選べばいいか
判断軸はシンプルです。
「1回だけ、1〜数個のファイルを送りたい」ならscpで十分です。
「継続的にディレクトリを同期する」「転送量やサーバー負荷を抑えたい」ならrsyncを選びましょう。
実務では、初回のデプロイや簡単な設定ファイルの受け渡しにはscpを、CI/CDでの自動デプロイや定期バックアップにはrsyncを使う、という使い分けが一般的です。
よくあるつまずきポイント・エラー対処
ディレクトリ末尾のスラッシュ有無でrsyncの結果が変わる
私が実際にrsyncでディレクトリを転送しようとしたとき、想定と違う結果になったことがあります。
❌ Before
# 末尾にスラッシュを付けずに実行
$ rsync -avz ./project user@203.0.113.10:/home/user/project/
このコマンドを実行すると、サーバー側に/home/user/project/project/という二重のディレクトリが作られてしまいました。
原因は、コピー元パスの末尾にスラッシュがあるかどうかで、rsyncの挙動が変わることを知らなかったためです。
✅ After
# 末尾にスラッシュを付けると「中身だけ」を転送する
$ rsync -avz ./project/ user@203.0.113.10:/home/user/project/
./project(スラッシュなし)は「projectディレクトリごと」を転送し、./project/(スラッシュあり)は「project以下の中身だけ」を転送します。
この違いはrsync特有のつまずきポイントなので、意識して使い分けるようにしています。
scpでPermission deniedになる
サーバーの権限が足りないディレクトリへコピーしようとして、次のエラーに遭遇したこともあります。
❌ Before
$ scp ./app.zip user@203.0.113.10:/var/www/app.zip
scp: /var/www/app.zip: Permission denied
コピー先の/var/wwwディレクトリの所有者がrootで、接続ユーザーに書き込み権限がなかったことが原因でした。
✅ After
# 一度ホームディレクトリにコピーしてから、サーバー側でsudoを使って移動する
$ scp ./app.zip user@203.0.113.10:/home/user/
$ ssh user@203.0.113.10 "sudo mv /home/user/app.zip /var/www/app.zip"
権限が必要なディレクトリへ直接scpすることはできないため、一度書き込み可能な場所へ転送してから、L14で紹介したsudoでサーバー側の操作として移動する流れが安全です。
応用・一歩先の使い方
転送速度に制限をかける
本番サーバーの通信帯域を圧迫したくない場合は、rsyncの--bwlimitオプションで転送速度を制限できます。
# 転送速度を1000KB/sに制限する
$ rsync -avz --bwlimit=1000 ./project/ user@203.0.113.10:/home/user/project/
営業時間中にバックアップを取りたい場合など、他の通信への影響を抑えたい場面で有効です。
除外ファイルを指定する
.gitディレクトリやnode_modulesなど、転送する必要のないファイルは--excludeで除外します。
$ rsync -avz --exclude=".git" --exclude="node_modules" ./project/ user@203.0.113.10:/home/user/project/
除外パターンが多い場合は、.rsync-ignoreのようなファイルにまとめて--exclude-fromで読み込ませると管理しやすくなります。
まとめ
この記事のポイント
- scpはSSH経由でファイルを1回コピーするシンプルなコマンド
- rsyncは差分だけを転送する高機能な同期コマンド
- 単発のコピーはscp、継続的な同期やデプロイはrsyncが向いている
- rsyncはコピー元パスの末尾スラッシュの有無で挙動が変わる点に注意する
--deleteは--dry-runで事前確認してから実行するのが安全
次に読むべき記事
- L20「SSH接続の基本:リモートサーバーに安全に繋ぐ」で転送の前提となるSSH接続を確認する
- L14「sudoの仕組みと安全な使い方」で権限が必要な操作の扱い方を学ぶ
- L23「よくあるLinuxエラーとトラブルシューティング」でさらに幅広いエラー対処を確認する