今まで余り考えずクライアント側のコマンドをただ実行するだけで知らなかったのだが、scpには-t
、-f
というオプションがあるらしい。
このオプション付きでサーバ側でscpを実行することで、標準入力から処理内容を受け付けてファイルを転送しているそうだ。
1. ローカルからリモートへ転送する場合
ローカルからリモートに転送する場合は、以下のように改行区切りで指示を出し、それをパイプでscpに渡す。 転送する対象となるファイルPATHやサイズを指定して、次にその中身を出力している。1ファイルにつき1回づつ転送することになるようで、配下のディレクトリを指定したら自動で作成されるようだ。
{ echo D0755 0 test_dir3; echo C0644 12 test1; printf 'hello\ntest1\n'; printf \\000; } | scp -rt /tmp
blacknon@test-ubuntu:~$ { echo D0755 0 test_dir3; echo C0644 12 test1; printf 'hello\ntest1\n'; printf \\000; }
D0755 0 test_dir3
C0644 12 test1
hello
test1
blacknon@test-ubuntu:~$ { echo D0755 0 test_dir3; echo C0644 12 test1; printf 'hello\ntest1\n'; printf \\000; } | scp -rt /tmp
test1 100% 12 0.0KB/s 00:00
blacknon@test-ubuntu:~$ ls -al /tmp/test_dir3/
合計 12
drwxr-xr-x 2 blacknon blacknon 4096 5月 6 00:42 .
drwxrwxrwt 15 root root 4096 5月 6 00:42 ..
-rw-r--r-- 1 blacknon blacknon 12 5月 6 00:42 test1
blacknon@test-ubuntu:~$ cat /tmp/test_dir3/test1
hello
test1
複数ファイルを送信する場合、Nullキャラクタで区切った後に送信内容(ファイル名、サイズ、中身)を送信しているようだ。
{ echo D0755 0 test_dir3; \
echo C0644 12 test1; \
printf 'hello\ntest1\n'; \
printf \\000; \
echo C0644 12 test2; \
printf 'hello\ntest2\n'; \
printf \\000; } | scp -rt /tmp
blacknon@test-ubuntu:~$ { echo D0755 0 test_dir3; \
> echo C0644 12 test1; \
> printf 'hello\ntest1\n'; \
> printf \\000; \
> echo C0644 12 test2; \
> printf 'hello\ntest2\n'; \
> printf \\000; } | scp -rt /tmp
test1 100% 12 0.0KB/s 00:00
test2 100% 12 0.0KB/s 00:00
blacknon@test-ubuntu:~$ ls -al /tmp/test_dir3/
合計 16
drwxr-xr-x 2 blacknon blacknon 4096 5月 6 00:53 .
drwxrwxrwt 15 root root 4096 5月 6 00:54 ..
-rw-r--r-- 1 blacknon blacknon 12 5月 6 00:53 test1
-rw-r--r-- 1 blacknon blacknon 12 5月 6 00:53 test2
blacknon@test-ubuntu:~$ grep '' /tmp/test_dir3/*
/tmp/test_dir3/test1:hello
/tmp/test_dir3/test1:test1
/tmp/test_dir3/test2:hello
/tmp/test_dir3/test2:test2
2. リモートからローカルへ転送する場合
リモートからローカルに転送する際、ローカル側からはNullキャラクタを(最低でも)7個渡すことで、指定したディレクトリ配下やファイルの内容を取得するようだ。ここで渡すNullキャラクタの個数だけ、scpから情報を取得できる(ファイルの中身は何行あってもNullキャラクタ1個分)。 (ちなみに、以下の例ではNullキャラクタが分かるよう、cat -Aに繋いでいる)
printf \\000\\000\\000\\000\\000\\000\\000 | scp -rf /tmp/test_dir3
blacknon@test-ubuntu:~$ printf \\000\\000\\000\\000\\000\\000\\000 | scp -rf /tmp/test_dir3 | cat -A
D0755 0 test_dir3$
C0644 12 test1$
hello$
test1$
^@C0644 12 test2$
hello$
test2$
^@E$
あとは、出力された内容を受け付けてファイルに書き出せばいい。 これをそのままscp -tで受け付けてもそのままファイルに書き出してくれる。
参考
- How the SCP protocol works (Jan Pechanec's weblog)(消えてたのでWebArchiveのリンク)