これはなにをしたくて書いたもの?
SSH越しにtar.gzやzipを圧縮、転送できないかな?と思いまして。
ちょっとやってみました。標準出力・標準入力をうまくつかってあげればよさそうです。
環境
ローカル、リモートともにUbuntu Linux 24.04 LTSとします。
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 24.04.1 LTS Release: 24.04 Codename: noble $ uname -srvmpio Linux 6.8.0-51-generic #52-Ubuntu SMP PREEMPT_DYNAMIC Thu Dec 5 13:09:44 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
OpenSSHのバージョン。
$ sshd -V OpenSSH_9.6p1 Ubuntu-3ubuntu13.5, OpenSSL 3.0.13 30 Jan 2024 $ ssh -V OpenSSH_9.6p1 Ubuntu-3ubuntu13.5, OpenSSL 3.0.13 30 Jan 2024
ローカルとリモートに、それぞれ以下のディレクトリを作成しておきます。
## ローカル $ mkdir local-dir ## リモート $ mkdir remote-dir
やってみること
以下のパターンを行ってみたいと思います。
- ローカルにあるファイルツリーをリモートにtar.gzまたはzip圧縮しつつ転送
- ローカルにあるファイルツリーをリモートにtar.gz圧縮しつつ転送、リモートで展開
- リモートにあるファイルツリーをローカルにtar.gzまたはzip圧縮しつつ転送
- リモートにあるファイルツリーをローカルにtar.gz圧縮しつつ転送、リモートで展開
接続にはSSHを使います。
ポイントは、圧縮ファイルを作ってから(または展開してから)送信しない、ですね。zipはこのやり方だと展開寺に
制限があるので、一部パターンに含まれていません。
ではやってみましょう。
tar.gz
.gzはなくてもいい気がしますが、まずはtar.gzから
ローカル → リモート
ローカルにあるファイルツリーをリモートにtar.gz圧縮しつつ転送してみましょう。
まずはローカル側にファイルを用意。
$ cd local-dir $ curl -LO https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.34/bin/apache-tomcat-10.1.34.tar.gz
1度展開して、オリジナルのtar.gzは消しておきます。
$ tar xf apache-tomcat-10.1.34.tar.gz $ rm apache-tomcat-10.1.34.tar.gz
展開後のディレクトリの中身。
$ ll apache-tomcat-10.1.34 合計 160 drwxrwxr-x 9 xxxxx xxxxx 4096 1月 25 16:02 ./ drwxrwxr-x 3 xxxxx xxxxx 4096 1月 25 16:02 ../ -rw-r----- 1 xxxxx xxxxx 21039 12月 6 01:01 BUILDING.txt -rw-r----- 1 xxxxx xxxxx 6166 12月 6 01:01 CONTRIBUTING.md -rw-r----- 1 xxxxx xxxxx 60393 12月 6 01:01 LICENSE -rw-r----- 1 xxxxx xxxxx 2333 12月 6 01:01 NOTICE -rw-r----- 1 xxxxx xxxxx 3298 12月 6 01:01 README.md -rw-r----- 1 xxxxx xxxxx 6776 12月 6 01:01 RELEASE-NOTES -rw-r----- 1 xxxxx xxxxx 16109 12月 6 01:01 RUNNING.txt drwxr-x--- 2 xxxxx xxxxx 4096 1月 25 16:02 bin/ drwx------ 2 xxxxx xxxxx 4096 12月 6 01:01 conf/ drwxr-x--- 2 xxxxx xxxxx 4096 1月 25 16:02 lib/ drwxr-x--- 2 xxxxx xxxxx 4096 12月 6 01:01 logs/ drwxr-x--- 2 xxxxx xxxxx 4096 1月 25 16:02 temp/ drwxr-x--- 7 xxxxx xxxxx 4096 12月 6 01:01 webapps/ drwxr-x--- 2 xxxxx xxxxx 4096 12月 6 01:01 work/
では、ローカルのディレクトリーをtar.gzしつつ、リモートに転送します。こんな感じですね。
$ tar czvf - apache-tomcat-10.1.34 | ssh [リモートユーザー]@[接続先ホスト] 'cat > ~/remote-dir/apache-tomcat-10.1.34.tar.gz'
汎化するとこうでしょうか。
$ tar czvf - [圧縮対象] | ssh [リモートユーザー]@[接続先ホスト] 'cat > [リモートでの保存するtar.gzのファイルパス]'
ポイントは、tarの出力先ファイル名を-にして標準出力にしていることですね。リモートではそのまま標準入力の内容を
catで保存します。
次は、ローカルのディレクトリーをtar.gzしつつリモートに転送した後、リモートで展開するパターン。
$ tar czvf - apache-tomcat-10.1.34 | ssh [リモートユーザー]@[接続先ホスト] 'tar xzf - -C ~/remote-dir'
今回の場合は、remote-dirディレクトリーの配下にapache-tomcat-10.1.34というディレクトリーが作られ中身が入ります。
汎化するとこうでしょうか。
$ tar czvf - [圧縮対象] | ssh [リモートユーザー]@[接続先ホスト] 'tar xzf - -C [リモートでの展開先のディレクトリー]'
リモート → ローカル
次は、リモートにあるファイルツリーをローカルにtar.gz圧縮しつつ転送してみます。
リモート側にファイルを用意。
$ cd remote-dir $ curl -LO https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.34/bin/apache-tomcat-10.1.34.tar.gz
1度展開して、オリジナルのtar.gzは消しておきます。
$ tar xf apache-tomcat-10.1.34.tar.gz $ rm apache-tomcat-10.1.34.tar.gz
リモートのディレクトリーをtar.gzしつつ、ローカルに転送します。こんな感じですね。
$ ssh [リモートユーザー]@[接続先ホスト] 'tar -C ~/remote-dir -czvf - apache-tomcat-10.1.34' > apache-tomcat-10.1.34.tar.gz
汎化するとこうでしょうか。
$ ssh [リモートユーザー]@[接続先ホスト] 'tar -C [リモートの圧縮対象があるディレクトリー] -czvf - [圧縮対象]' > [ローカルに保存する圧縮ファイル名]
やっぱり-がポイントで、標準出力に結果を書き出してローカルにはリダイレクトして単純にファイル保存します。
リモートのディレクトリーをtar.gzしつつリモートに転送した後、ローカルで展開するパターン。
$ ssh [リモートユーザー]@[接続先ホスト] 'tar -C ~/remote-dir -czvf - apache-tomcat-10.1.34' | tar zxf -
これで、ローカルにapache-tomcat-10.1.34というディレクトリーが作られ中身が入ります。
ローカルのtarコマンドは、fオプションでの指定を-にすることで標準入力を対象にします。
汎化。
$ ssh [リモートユーザー]@[接続先ホスト] 'tar -C [リモートの圧縮対象があるディレクトリー] -czvf - [圧縮対象]' | tar zxf -
zip
次はzipですね。
ローカル → リモート
ローカルにあるファイルツリーをリモートにzip圧縮しつつ転送してみましょう。
tar.gzと同じように準備。
$ cd local-dir $ curl -LO https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.34/bin/apache-tomcat-10.1.34.tar.gz $ tar xf apache-tomcat-10.1.34.tar.gz $ rm apache-tomcat-10.1.34.tar.gz
ローカルのディレクトリーをzip圧縮しつつ、リモートに転送します。こんな感じですね。
$ zip -r - apache-tomcat-10.1.34 | [リモートユーザー]@[接続先ホスト] 'cat > ~/remote-dir/apache-tomcat-10.1.34.zip'
ここでも-を使って、zipの出力先を標準出力にしているところがポイントです。
汎化。
$ zip -r - [圧縮対象] | [リモートユーザー]@[接続先ホスト] 'cat > [リモートでのzip保存先ファイルパス]'
ローカルのディレクトリーをzip圧縮しつつリモートに転送した後、リモートで展開するパターンはunzipが標準入力に未対応なので
できません。
他のコマンドだったりで代替手段を考えることになります。
リモート → ローカル
最後はリモートにあるファイルツリーをローカルにzip圧縮しつつ転送してみます。
リモート側の準備。
$ cd remote-dir $ curl -LO https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.34/bin/apache-tomcat-10.1.34.tar.gz $ tar xf apache-tomcat-10.1.34.tar.gz $ rm apache-tomcat-10.1.34.tar.gz
リモートのディレクトリーをzip圧縮しつつ、ローカルに転送します。こんな感じですね。
$ ssh [リモートユーザー]@[接続先ホスト] 'cd ~/remote-dir && zip -r - apache-tomcat-10.1.34' > apache-tomcat-10.1.34.zip
1度cdでディレクトリーを移動しているのは、zipファイルに含まれるパスの調整のためですね。指定したディレクトリーの
パスがすべて含まれていいのなら、zipコマンドの実行対象にそのパスを指定すればよいと思います。
汎化。
$ ssh [リモートユーザー]@[接続先ホスト] 'cd [リモートの圧縮対象があるディレクトリー] && zip -r - [リモートの圧縮対象]' > [保存先のzipファイルパス]
ローカルでunzipするのは、標準入力をサポートしていなのでやっぱりできません。
こんなところでしょうか。
おわりに
そういえばやったことがないな、と思って、ちょっと調べてみました。
標準出力を活用すると、いろんなことができるようで少し幅が広がりますね。
今回の内容はそこまで使うことはないような気はしますが、発想として覚えておくとよさそうかなと思います。