Piping Serverを使って起動直後のサーバにファイルをラクラク転送してみた!

2023.03.28

サクッと作ったサーバ上で何かしらの検証なんかをしたい時がちょくちょくあります。 例えば、ちょっと検証してさっと終了させたいというときはCloudShellの出番ですね。

CloudShellに限らず、手元のマシンからサーバにファイルやディレクトリを送りたい時はどうしていますか? scpとかを使うのが多いのでしょうか? CloudShellはAWS CLIなどの環境は整っているので、 S3にファイルを配置してそこを経由して送るような方法もありますね。 でもS3に接続するために何かしらの設定が必要だったり、 これだけでもちょっと面倒な時もあります。 もちろんもっと最小限の機能しか持たせないサーバの場合はもっと大変になります。

さて、そんな時に使いたいのがPiping Serverです。 Piping Serverの詳細については下記の記事を参照して欲しいのですが、 インターネットに繋がった環境同士であれば、難なくデータのやりとりが可能になります。

私はこの仕組みが大好きでよく使っています。

Piping Serverとは

一言で言うと、コマンドライン上での|(パイプ)を通しての処理が、 インターネットを介しても繋げられるというものです。

例えば、手元のMacで

env | cat -n > env.txt

とやるのと同じ要領で、

# 手元のMac                CloudShell上
  env       | (Internet) | cat -n > env.txt

ができます。

しかも、特別なソフトの導入も不要で、curlコマンドだけあれば動作します。 (Windows環境でもPowerShellのコマンドで同様のことができるようです)

簡単に試してみる

まずは簡単な例で試してみます。

送信するマシンと受信するマシンが別になっている前提で、それぞれでコマンドを実行して行きます。 まずは送信側です。

送信側

env | curl -T - https://ppng.io/cm-hirano-hogehoge

envで環境変数を出力した結果をcurl

https://ppng.io/cm-hirano-hogehoge

に送っています。ここで cm-hirano-hogehoge の部分は自分で好きな文字列を使うことができます。 (中継サーバ ppng.io については後述します。)

この

https://ppng.io/cm-hirano-hogehoge

は名前つきパイプのような動作をするので、 これを読み込む人がいない間はこの処理は終了しません。(正確にはデータの送信も開始しません)

次に受信側です。送信側は上記の状態でデータ受信者が現れるのを待っている状態のままにしておきます。

受信側

curl https://ppng.io/cm-hirano-hogehoge | cat -n > env.txt

curlで先ほどのURLからデータを読み取ります。 その結果をパイプを使って次のコマンドに送っています。 今回は適当に行番号だけつけてファイルにリダイレクトしています。 これだけで手元の情報をインターネット越しに別のマシンに送ることができました!

先ほどの

env | (Internet) | cat -n > env.txt

における (Internet) の部分を、ほぼ

https://ppng.io/cm-hirano-hogehoge

に置き換えただけでマシンを跨ぐことができました!

これは実際にやってみないと何がすごいのかよくわからないかもしれません。 送信・受信ともにローカルマシンでも問題なく動作しますので、 まずはそれでも良いのでちょっと試してみてください!

中継サーバについて

上記のppng.ioはPiping Serverの開発者の方が善意で立ててくれているサーバとなります。 Piping Serverはサーバに何かデータが溜まったりしていく性質ではないので、 多くの人が同時に使ってもかなり捌いてくれるかとは思いますが、 ヘビーユースする場合は当該記事を読んで自前のサーバを立ててご利用ください。

注意点

この単純な利用の場合、 中継するURLさえ合致していれば誰でもデータを受信することができます。 なので、最低限でも以下のことを気をつけて使うのが良さそうです。

  • 他の人と被りそうなあまりにも単純な名前は避ける
    • できればランダムな英数字とかを入れるのが良さそう
  • 受信側を先に実行させる
    • 待ち受ける側を先に起動しておけば名前が確保されるので、他の人にデータを取られる心配がない

ファイルを送ってみる

ファイルとは本来ただのバイナリ列ですから、 単純にcatしてリダイレクトしたらコピーができます。 ローカルで言えば、

cat orig.png > copy.png

でコピーができます。 テキストに限らずバイナリファイルでも全く問題ありません。 これができるということは、Piping Serevrを使えばマシン間でのファイル転送が可能になります。 やってみましょう。 (ここからは上記注意点を考慮して受信側から記載します)

受信側

$ curl https://ppng.io/cm-hirano-hogehoge > copy.png

送信側

$ cat orig.png | curl -T - https://ppng.io/cm-hirano-hogehoge

ということで、ファイルの転送ができました。 もちろんこれは圧縮したzipファイルなども全く同様に送れるので、 原理的にあらゆるファイルを転送することができます。

また作者の方が書かれている通り、 データはストリーミング形式で転送されるだけ(横流しされるだけ)なので、 大容量のファイルでも中継サーバのリソースを気にする必要がありません。 作者の方の実験では868TBのデータの転送も問題なくできているとのことです!!

中間ファイルを一切作らずに送る

ここまで簡単にファイルが転送できると、 もはや転送するために一時的にパッケージングしたファイルを生成することすら省略したくなるのが人情というものです。 tar.gzを使ってやってみましょう。

受信側

$ curl https://ppng.io/cm-hirano-hogehoge | tar zxpf - -C .

送信側

$ tar zcf - dir_a dir_b file_c file_d | curl -T - https://ppng.io/cm-hirano-hogehoge

これで、ファイルとディレクトリが混合されたものでも、 中間のファイルを一切残すことなく、そのままのディレクトリ構成で受信先に展開されます。

使用したtarのオプションについても簡単に記載しておきます。

  • c
    • tarファイルにまとめる
  • z
    • gzip圧縮・解凍する
  • f -
    • これで標準入出力が使える
  • x
    • tarファイルを展開する
  • p
    • パーミッションをもとと同じにする
  • C
    • 処理を指定ディレクトリに移動して行う

end-to-end暗号化して送る

機密性のあるデータを送る場合はきちんと暗号化することも視野に入れましょう。 (暗号化の有無に関わらず素性を知らないサーバにデータを送っても良いかは別途必ず考慮してください)

こちらもopensslがあればコマンドラインからサクッといけます。 $PASSWORDで任意のパスワードを設定して暗号化して、 転送先で同じパスワードで復元します。

受信側

$ curl https://ppng.io/cm-hirano-hogehoge | openssl aes-256-cbc -d -k "$PASSWORD" | tar zxpf - -C .

送信側

$ tar zcf - dir_a dir_b file_c file d | openssl aes-256-cbc -k "$PASSWORD" | curl -T - https://ppng.io/cm-hirano-hogehoge

これでサーバを経由する部分では全て暗号化が適用されたデータになりますので、 end-to-endで暗号化を適用することができました。

まとめ

Piping Serverを利用して、 インターネットに接続されているPC間でディレクトリやファイルを、 構成も変えずに簡単に共有できました。 第三者的な場所にファイルを置いたりすることもなく、 そのための何か特別な通信ソフトを導入する必要もありません。 curlが入っている環境なら一切準備不要です。

クラウド上にサーバを立てても、 手元のファイルを送るだけで結構苦労したりすることも多いですし、 インターネットに繋がってさえいれば汎用的に使うことができるので、 是非試してみてください!