ゴクゴクたま~にだが、ログインユーザに権限のないディレクトリ(rootの所有しているディレクトリとか)に対してscpを実行したい、といった事がある。

ただscpコマンドは基本的にそのような機能は有しておらず、リモート側でsudo経由でscpを実行してくれるような挙動はしてくれない。なので、大体こういった場合には(前にもここに書いたのだけど)一度tarで固めた後にsshにパイプで渡して、それをそのまま展開してしまう方法が一般的…というか楽だ。

tar zcf - /path/to/dir | ssh -t user@host 'sudo "cat|tar zx -C /path/to/dir"' # リモートサーバにコピーする場合
ssh -t user@host 'sudo "tar zcf - /path/to/dir"' | tar xz -C /path/to/dir  # リモートサーバからコピーする場合

じゃあ、リモートサーバ側で権限の無いディレクトリに対して、sudo等を利用してscpでファイル転送できないかというと、そうでもないようだ。 別件の対応でscpについて調べていたところ、どうやらscpには-t,-fオプションというものがあるらしい(manには載ってない)。通常のscpも、サーバ側でこれを実行させることでファイルの転送をしているようだ。

で、この-t(to)、-f(from)オプション、標準入出力で転送内容(ファイル名だったりパーミッション、ファイルの中身)をやり取りしている。 とうことは、標準入出力にノイズ(sshやsudo実行時のパスワードとか)がなければこれでファイルの転送ができそうだ。

…という訳で、実際やってみたところ、以下のようにコマンドを実行すればリモート側でsudoを使ってscpでファイルの転送ができた。sudo及びsshでパスワード入力が無いように設定する必要があるので注意。 (あと、local→remote時はアラートメッセージが出る場合がある)

printf \\0"%.s" {1..10000} | scp -rf ./from_dir | ssh -t user@host 'sudo -s bash -c "cat|scp -rt /root/to_dir"'
ssh -t user@host 'sudo -s bash -c "printf \\\000\"%.s\" {1..1000}|scp -rfq /root/from_dir/"'|sed 's/\r//g'|scp -rt ./to_dir

…まぁ試しといてなんだけど、使いにくい事この上ない。 実務でこんなんターミナルに打ち込みたくない。 できなくはないけど、これでやるのは現実的じゃないだろう。

普通に実務で利用するのなら、最初に記述しているよう、tarでアーカイブ化してssh経由で送る方法を取るといいだろう。