PR

【Ubuntu】scpでデータをコピーする方法

Ubuntuでscpを使ってネットワーク越しにデータをコピーする方法です。

scpとは

「scp」は「SSH」で暗号化された通信経路を使用して、ネットワーク越しにファイル等をコピーするコマンドです。

「SSH」を使ってデータの転送を行う方法として「sftp」もありますが、コピーするデータの数が少ないのであれば「scp」の方が対話形式ではないため簡単にデータのコピーを行うことができます。

「scp」でデータをコピーする際の注意点

「scp」を使用する際の注意点としては、同名のファイルやディレクトリがコピー先にあった場合、問答無用で上書きしてしまいますので十分に注意して作業を行ってください。

「scp」の使用方法

「scp」の基本的な使い方は「cp」コマンドと同じで、下記のようにデータのコピー元とコピー先を指定して使用します。

リモートホストからデータをコピー

ネットワーク越しのリモートホストからデータをコピーするには、下記の書式でデータのコピー元とコピー先を指定します。

scp ユーザ@リモートホスト:コピー元データ ロカールホストのコピー先ディレクトリ

リモートホストへの接続ユーザ部分の指定を省略すると、ローカルホストにログインしているユーザが指定されます。

実行例

リモートホスト(192.168.1.130)から「/home/tamohiko/10M」というデータを、ローカルホストの「./」(現在のディレクトリ)にコピーしてみます。

ログインパスワードの入力を求められるので、SSHで接続する際のパスワードを入力してあげてください。

$ scp tamohiko@192.168.1.130:/home/tamohiko/10M ./
tamohiko@192.168.1.130's password:
10M                  100%   10MB  10.0MB/s   00:00

ローカルホストからデータをコピー

ローカルホストにあるデータをリモートホストにコピーする場合は、下記の書式でデータのコピー元とコピー先を指定します。

scp ローカルホストのデータパス ユーザ@リモートホスト:コピー先ディレクトリ

実行例

ロカールホストの「10M」というファイルを、リモートホスト(192.168.1.130)の「/home/tamohiko/work」というディレクトリにコピーしてみます。

$ scp ./10M tamohiko@192.168.1.130:/home/tamohiko/work/
10M                       100%   10MB   4.9MB/s   00:02  

秘密鍵や接続ポート番号を指定する場合

SSHの接続に秘密鍵が必要な場合や、接続するポート番号を22番ポートから変更している際には、以下のオプションを使用します。

  • -i 秘密鍵
  • -P ポート番号

リモートホストからローカルホストへデータをコピーする場合は以下の書式となります。

$ scp -i 秘密鍵 -P ポート番号 ユーザ@リモートホスト:コピー元データ ロカールホストのディレクトリ

ローカルホストからリモートホストへデータをコピーする場合は以下の書式となります。

$ scp -i 秘密鍵 -P ポート番号 ロカールホストのデータ ユーザ@リモートホスト:コピー先ディレクトリ 

実行例

「-i」と「-P」オプションの使用例として、以下のリモートホストからローカルホストへのデータコピーと、ローカルホストからリモートホストへのデータコピーを実行します。

  • リモートホストアドレス: 192.168.1.1
  • 接続ユーザ: tamohiko
  • 秘密鍵: ~/.ssh/id_ed25519
  • SSH接続ポート: 10022
リモートホストからロカルホストへコピー

リモートホストの「10MB_DATA」というファイルを、ローカルホストの「./」(現在のディレクトリ)にコピーします。

秘密鍵にパスフレーズを設定している場合は入力を求められます。

$ scp -i ~/.ssh/id_ed25519 -P 10022 tamohiko@192.168.1.1:10MB_DATA ./
Enter passphrase for key '/home/tamohiko/.ssh/id_ed25519': 
10MB_DATA                           100%   10MB  99.1MB/s   00:00            
ローカルホストからリモートホストへコピー

ローカルホストの「10MB_DATA」というファイルを、リモートホストの「/home/tamohiko/work/」ディレクトリにコピーします。

$ scp -i ~/.ssh/id_ed25519 -P 10022 ./10MB_DATA tamohiko@192.168.1.1:/home/tamohiko/work/
Enter passphrase for key '/home/tamohiko/.ssh/id_ed25519': 
10MB_DATA                                   100%   10MB  41.6MB/s   00:00   

「~/.ssh/config」を使って簡単に「scp」を実行しよう

「~/.ssh/config」には、SSHでリモートホストに接続するための情報を設定しておくことが出来ます。

「scp」を実行するユーザで「~/.ssh/config」ファイルに、接続先ホストの接続ポートや秘密鍵の場所等を設定しておくことで、とても簡単に「scp」を実行することが出来るようになります。

「~/.ssh/config」の作成

「~/.ssh」ディレクトリが存在していない場合はディレクトリを作成します。

$ mkdir ~/.ssh
$ chmod 700 ~/.ssh

「~/.ssh/config」にSSH接続用の設定を行います。

$ vi ~/.ssh/config

基本的な設定内容は下記の通りです。

「IdentityFile 秘密鍵」と「IdentitiesOnly yes」の項目は、SSH接続に秘密鍵が必要な場合に設定します。

Host 設定名(サーバ名等を記述)
    HostName 接続先サーバアドレス
    User 接続ユーザ
    Port ポート番号
    TCPKeepAlive yes
    ServerAliveInterval 60
    IdentityFile 秘密鍵  # 秘密鍵を指定
    IdentitiesOnly yes   # 鍵認証方式の場合 yes

下記情報のリモートホスト設定例です。

  • リモートホストアドレス: 192.168.1.1
  • 接続ユーザ: tamohiko
  • 接続ポート: 10022
  • 秘密鍵: ~/.ssh/id_ed25519

設定名は「host_a」としています。

Host host_a
    HostName 192.168.1.1
    User tamohiko
    Port 10022
    TCPKeepAlive yes
    ServerAliveInterval 60
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

動作検証

設定名に指定した名前でSSH接続が出来るか確認します。

$ ssh host_a

秘密鍵にパスフレーズが設定されている場合は入力を求められるので、設定されているパスフレーズを入力してください。

これでSSH接続できれば設定は完了です。

「~/.ssh/config」についてより詳しい説明を下記ページで行っていますので、よければ参考にしてみてください。

【Ubuntu】「~/.ssh/config」を使って簡単にSSHの接続を行う方法
Ubuntuから別のサーバにSSHで接続を行う際に、接続先の設定を保存しておいて簡単に接続できるようにする方法です。「~/.ssh/config」で簡単SSH接続SSHで接続を行う際にポート番号を変更していたり鍵認証方式を採用している場合、...

scp実行例

「~/.ssh/config」に設定を行うと、リモートホストを「host_a」と記述するだけになるので、入力する文字数がかなり少くなくなるため、下記のようにとても簡単に「scp」コマンドを実行することが出来るようになります。

$ scp ./10MB_DATA host_a:/home/tamohiko/work/

オプションの説明

「scp」を使用するにあたり、普段使いそうなオプションを抜粋して説明していきます。

オプション 説明
-p コピー元データの更新時間、パーミッション情報を保持させる
-q サイレントモード
実行状況などの詳細状況を表示させない
-r フォルダをコピーする際に使用
ディレクトリ内のデータを再帰的にコピーする
-v 冗長表示モード
詳細な経過情報を表示させる(デバッグ時などに使用)
-C データを圧縮しコピーする

-p 更新時間やパーミッション情報を保持

「-p」オプションと使うと、コピー元ファイルの時刻情報やパーミッションを保持させたままデータをコピーすることが出来ます。

ローカルホストにある「10MB_DATA」というファイルを使って「-p」オプションの有りと無しで、コピー後のファイルの情報を比べてみます。

$ ls -l 10MB_DATA 
-rw-rw-r-- 1 tamohiko tamohiko 10485760  2月  7 10:49 10MB_DATA

「-p」 オプションなし

「-p」オプションを指定せずに「scp」を行います。

$ scp ./10MB_DATA host_a:/home/tamohiko/work
10MB_DATA                                     100%   10MB   3.1MB/s   00:03

リモートホストでコピーしてきたファイルの情報を確認すると、ファイルのタイムスタンプが「scp」してきた時間に変更されていることが確認できました。

$ ls -l 10MB_DATA 
-rw-rw-r-- 1 tamohiko tamohiko 10485760 Feb  8 22:33 10MB_DATA

「-p」 オプションあり

次に「-p」オプションを指定して「scp」を行います。

$ scp -p ./10MB_DATA host_a:/home/tamohiko/work
10MB_DATA                                     100%   10MB   2.7MB/s   00:03 

リモートホストでコピーしてきたファイルの情報を確認すると、ファイルのタイムスタンプはローカルホストにあるファイルと同じであることが確認できました。

$ ls -l 10MB_DATA 
-rw-rw-r-- 1 tamohiko tamohiko 10485760 Feb  7 10:49 10MB_DATA

-q サイレントモード

「-q」オプションを使用すると、データのコピー状況についての情報が表示されなくなります。

$ scp -q ./10MB_DATA host_a:/home/tamohiko/work

私は、シェルスクリプトで「scp」を実行する場合にこちらのオプションを使うことが多いです。

-r ディレクトリをコピー

「scp」でディレクトリをコピーする場合は「-r」オプションを使用します。

「-r」オプションを使用せずにディレクトリをコピーしようとすると、「not a regular file」とメッセージが表示されて失敗してしまいます。

$ scp ./test_dir/ host_a:
scp: local "./test_dir" is not a regular file
scp: failed to upload file ./test_dir to .

「-r」オプションを使用すると、以下のようにディレクトリのコピーを行うことが出来ます。

$ scp -r ./test_dir/ host_a:
10MB_DATA_2           100%   10MB   4.3MB/s   00:02

-v 詳細な経過情報を表示

「-v」オプションを使用すると「scp」を実行する際の詳細情報を表示してくれます。

「scp」の動作に問題が発生した場合などは、このオプションを使用することで原因を調査することが出来ます。

$ scp -v ./10MB_DATA host_a:/home/tamohiko/work
Executing: program /usr/bin/ssh host host_a, user (unspecified), command sftp
OpenSSH_9.6p1 Ubuntu-3ubuntu13.5, OpenSSL 3.0.13 30 Jan 2024
debug1: Reading configuration data /home/tamohiko/.ssh/config

### 中略 ###

debug1: pledge: fork
10MB_DATA                                     100%   10MB   3.1MB/s   00:03    
scp: debug1: truncating at 10485760
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
Transferred: sent 10497228, received 8352 bytes, in 4.3 seconds
Bytes per second: sent 2424109.1, received 1928.7
debug1: Exit status 0

-C データを圧縮してコピー

「-C」オプションを使用すると、データを圧縮してデータのコピーを行ってくれます。

圧縮が効くデータの場合はデータのコピーに掛かる時間がが短くなることが期待できますが、すでに圧縮済みのデータであったり圧縮があまり効かないデータの場合は、コピー時間が短くなることにはそれほど期待はできません。

テスト用に100MBのデータを作成して「-C」オプションの有り・無しでコピー時間の比較をしてみます。

$ dd if=/dev/zero of=100MB_ZERO_DATA bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.102961 s, 1.0 GB/s

ちなみに、今回作成したデータは「/dev/zero」で作成しているので、「gzip」で圧縮してみると下記のように圧縮がかなり効きます。

$ gzip -c 100MB_ZERO_DATA > 100MB_ZERO_DATA.gz
$ ls -lh 100MB_ZERO_DATA*
-rw-rw-r-- 1 tamohiko tamohiko 100M  2月  9 22:52 100MB_ZERO_DATA
-rw-rw-r-- 1 tamohiko tamohiko 100K  2月 10 10:41 100MB_ZERO_DATA.gz

まずは「-C」オプションを使用せずに「scp」でデータのコピーを行ったところ、コピーに掛かった時間は約20秒という結果になりました。

$ scp 100MB_ZERO_DATA host_a:work/
100MB_ZERO_DATA            100%  100MB   4.9MB/s   00:20

次に「-C」オプションを使用して「scp」を実行してみたところ、コピーにかかった時間は約2秒という結果になり、かなりコピーに掛かる時間が短縮されました。

$ scp -C 100MB_ZERO_DATA host_a:work/
100MB_ZERO_DATA            100%  100MB  45.6MB/s   00:02  

圧縮済みデータでの比較

すでに圧縮されているデータを使って、「-C」オプションの有無によってどのくらいコピー時間が変わるかの比較をしてみます。

テスト用のデータとして、以下の圧縮済みファイルを用意しました。

$ ls -lh vpslife.tar.gz 
-rw-rw-r-- 1 tamohiko tamohiko 90M  2月 10 10:01 vpslife.tar.gz

まずは、「-C」オプション無しで「scp」を実行すると、コピーに掛かった時間は約17秒となっています。

$ scp  vpslife.tar.gz host_a:work/
vpslife.tar.gz                 100%   89MB   5.2MB/s   00:17  

次に「-C」オプションを使用して「scp」を実行してみたところ、コピーに掛かった時間は約17秒という結果になり、「-C」オプション無しの場合とほぼ同じ結果となりました。

$ scp -C vpslife.tar.gz host_a:work/
vpslife.tar.gz                 100%   89MB   5.3MB/s   00:17         

すでに圧縮されているデータを再圧縮したとしても、基本はもう圧縮できないということですね。

コメント

タイトルとURLをコピーしました