CLOVER🍀

That was when it all began.

SSH越しにtar.gz、zipを圧縮、転送する

これはなにをしたくて書いたもの?

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はこのやり方だと展開寺に
制限があるので、一部パターンに含まれていません。

お題はApache Tomcatにします。

ではやってみましょう。

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が標準入力に未対応なので
できません。

他のコマンドだったりで代替手段を考えることになります。

標準入力からunzipしたい - CLOVER🍀

リモート → ローカル

最後はリモートにあるファイルツリーをローカルに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するのは、標準入力をサポートしていなのでやっぱりできません。

標準入力からunzipしたい - CLOVER🍀

こんなところでしょうか。

おわりに

そういえばやったことがないな、と思って、ちょっと調べてみました。

標準出力を活用すると、いろんなことができるようで少し幅が広がりますね。

今回の内容はそこまで使うことはないような気はしますが、発想として覚えておくとよさそうかなと思います。