ネットワーク越しでパイプしたり、あらゆるデバイス間でデータ転送したい!
ネットワーク越しでパイプしたり、あらゆるデバイス間でデータ転送したい!:
Mac, Windows, Linux, iPhoneやAndroidのスマホ・タブレットとかのデバイス間でデータの転送したいことがあります。
SlackとかLineとかSkypeとかAirDropとかあっても
すでにたくさんのファイル共有系のサービスがありますが、コマンドを使ったCUIベースにあまり親切な設計なものはあまりないと思います。
そこで、上記の問題を解決するために、以下のようなファイル転送の仕組みを作りました。
データの送信者も受信者も転送するためにインストールするものはありません。
curlコマンドやブラウザなどHTTP通信ができるものがあれば転送できます。
以下のデモでは、
これは
以下のように、
エンドツーエンドの暗号化なども可能です。
パイプが使えるということは、、圧縮や暗号化など、また2つ組み合わせて圧縮+暗号化すること可能です。
圧縮送信:
解凍送信:
や
暗号化送信(共通鍵):
復号化受信(共通鍵):
暗号化に
一時的なファイルも経由せず、時間的にも空間的にも効率が良く、パイプの素晴らしい可能性が発揮できます。
他にもパイプを使った便利なデータ転送を後述します。
最小の転送機能を搭載したWeb Clientでもファイルを送ったり受け取ったりすることが可能です。
IE10やIE11でも動作可能でした。
以下のデモのようにターミナルからブラウザに画像ファイルを送ることも簡単です。
以下のようにブラウザからもファイルを送ることができ、
まとめると、
プロジェクトはPiping Severと呼んでます。デバイス間のデータをネットワーク越しでパイプさせたい思いをこめました。
サーバーサイドTypeScriptです。
GitHub: https://github.com/nwtgck/piping-server
どこかのサーバーが独占するわけではなく、サーバーは自由にたくさん立てるポリシーです。好きに自分用のサーバーを立ていただければと思います。デモ用にいくつかサーバーを立てました。 1
その他個人的な運用では、LAN内にPiping Serverを立ててLANではより高速かつ閉じた転送するのに使ってます。主にLAN内ではSSHなどが使えない場合、特にLinux<=>Windowsなどで使ってます。
使い方が忘れたときはGET /helpで簡単にヘルプが確認できます。
サーバーの立てやすさもこだわっていて、
HTTPを使います。また、NAT超え問題を解決するために、サーバーが送信者と受信者の経由役になります。おそらくピアツーピア(P2P)のTURNサーバに似たものだと思います。
多くのデバイス・OSでの利用できるようにするためとインストール不要を実現するために、
広く広まっているプロトコルでの通信が不可欠です。そこで通信はHTTP/HTTPSを使います。
CUIからは、
macOS, Ubuntu, Amazon Linuxなどよく使われているOSには最初から入っています。しかも
HTTPを使っているため、GUIでもブラウザからデータを送ることも受け取ることもです。
ブラウザならMacでもWindowsでもiPhoneやAndroidなどのスマホ・タブレットでも使えます。
送受信は手軽行えるように極限までシンプルしました。
このストリーミングのおかげでUnix/Linuxのパイプと親和性が高く、効率よく、大きなデータの転送が可能になりました。
セキュリティに関してはデータ転送においてとても重要なところです。
まず、HTTPSを使っていれば、クライアント<=>サーバー間は暗号化されます
上記に書いた
上で紹介したデモ動画だと、「送信者がPOST/PUTしたあと、、受信者がGET」という順序ですが、「受信者がGET、送信者がPOST/PUT」の順序でも送信できます。後者のほうがよりセキュリティ的には良い思います。
理由としては前者だとの方法だと、送信者が先に送る準備をしてしまうため、真の受信者がGETする前に、他の受信者がそのパスを指定しまうと、データを得れるからです。もちろんパスを十分に推測不能なものにすればいいのですが、その状況を防げるGET firstがより安全です。
パスは早いものが勝ちになるので、以下のように既に受信者がいる場合は拒否されます。たまたま、ぶつかる可能性があるときも先にGETして予約していたほうが、送信者との安全なコネクションがはれると思います。
サーバーに保存されないため、一度ストリームが流れてしまうと同じデータを受け取りたい人に送るときの効率が悪いです。それを解決するための機能になってます。
データの元のストリームがあってそれを複数に分配するような仕組みが必要です。イメージ的には以下の図のようになります。
サイバーサイドTypeScriptなので、Node.jsを使っています。
stream.PassThroughを使って実現が可能です。
StackOverflowに短い例があったので、引用させていただきます。
下の例だと
ソース:javascript - Node.js Piping the same readable stream into multiple (writable) targets - Stack Overflow
HTTPサーバーを作るときの
実際にPiping ServerでのPassThoughを使っている箇所は以下になります。
https://github.com/nwtgck/piping-server/blob/eb40fe251b2a552348a4f8f8e635529460f2b4fa/src/piping.ts#L299-L362
すぐに気軽に立てれるように、いくつかサーバ立てる方法を用意しています。
Herokuに立てる方法についてです。
以下のPiping Serverのリポジトリにあ紫色の[Deploy to Heroku]を押すと、手軽にデプロイできます。
GitHub: https://github.com/nwtgck/piping-server
zeit/pkgを使って、npmで管理されているプロジェクトをポータブルなバイナリしています。
以下のコマンドで、ダウンロードして、実行権限を与えて http://localhost:8888にPiping serverが立ち上がります。
環境を汚さないのと導入が手軽なのがメリットです。
以下の
Alpineベースのイメージのためそこそこ軽量です。
Piping serverはデータを保存しないので、
Docker imageもgitのタグがつくと、Docker automated buildで自動でイメージがビルドされるようになっています。
Piping Serverはnpmのパッケージなので、以下のようにインストールすることができます。
以下のように起動させると、http://localhost:8888にPiping Serverが立ち上がります。
これもgitのタグがつくと自動で、npm publishされるようにCIで自動化して人為ミスなどを減らしています。
これは実験的なプロジェクトです。
bytenodeというJavaScriptをGoogle V8のバイトコードに事前にコンパイルしてそれを実行するプロジェクトがあり、それを利用したDocker imageです。メリットとしてはDocker imageが軽量です。
webpackなどの代替のparcelを使って、bundleして、それをバイトコードしてそれだけでalpineベースのDocker imageに乗せているので、より軽量なイメージになっています。
これも実験的なので別リポジトリです。
https://github.com/nwtgck/bytenode-piping-server
イメージ名以外起動方法が変わりませんが、イメージサイズがより軽量です。
現在実験的なプロジェクトです。ある程度使ってみて安定してそうだったら、本家のイメージもこの方法で作るようになるかもしれません。
「HTTPってどこまで大きいファイル送れるの?」 「HTMLとかRESTのAPIサーバーとか小さいデータを返すイメージしかない」という疑問に関してです。
Piping serverで無限にデータを送り続ける実験を47日前に開始しました。現在も進行中で、その結果では現在868テラバイトのデータが転送できています。
無限に送るのは単純で
この結果から少なくともlocalhostなら868テラバイトは転送できることが体感できました。
この記事でよく登場している
PUTではなくPOSTを使いたいときは、以下でもできます。ただPiping ServerではタイプしやすいようにPUTに対応してます。
オリジナルの実装がTypeScript/Node.jsです。そこで、Go言語で最小限のPiping Serverを実装して転送速度の比較しました。転送にかかる時間は大きく差があればあるほど、アップロード・ダウンロードともにユーザー体験が損なわれるので、調べました。比較対象としてGoを選んだのは、新しいサービスがGoで書かれていることが多くGoとの比較に興味があったのと、ネイティブな実行形式を作り出せるGoとスクリプト言語のJavaScriptでどれだけ差があるか知りたかったからです。
比較と言っても、そこまできっちりしたベンチーマークとかではなく、実際に送ってみて何MB/secか目視で確認する感じです。結果的にはそこまで顕著な差で出なさそうなことが分かりました。動画として結果を記録しました。
TypeScript/Node.js
YouTube: https://youtu.be/ufijpqHlJww
(https://github.com/nwtgck/piping-server)
Go言語
YouTube: https://youtu.be/NuKvDwB9JSU
(https://github.com/nwtgck/go-piping-server)
クライアントは無限に
よく使いそうな例をまとめます。
パイプの可能性が発揮できそうな面白いものも後ろの方にまとめました。
ポイントは、以下のどちらのコマンドも一時ファイルを作らずにストリームでzipやtar.gzを作って、ディレクトリを転送できるところです。
汎用的な方法は、以下のようにパイプとパイプの間に挟むことで進捗がわかります。
ファイルを送りたいときは、以下のように
PowerShellを使う方法の紹介です。
PowerShellは以下のアイコンのやつです。コマンドプロンプトとは別のアプリケーションで、少なくともWindows 10なら標準で入っているはずです。
(PowerShellが使えなくても、ブラウザでファイルの送信・受信が可能です)
PowerShellはWindowsに限ったものではなく、マルチプラットフォームを目指しているようです。
個人的に一番お手軽に試せると思うのがDockerを使った方法です。
以下のコマンドでシェルが立ち上がります。
viやvimなどのエディタを使って一時ファイルを作らずにPiping Serverに送る方法です。
以下のように、
以下のように、
送りながらハッシュ値を計算することで、より自信をもってデータを転送できます。
これのポイントも同じく、一時ファイルを作らずにストリーミングしながらハッシュ値を計算しているところです。
上記のコマンドを理解するためには、
以下のようにmp4の動画をPiping Serverに送って、ブラウザで開けば簡易的なストリーミングで動画が視聴できます。
ポイントは、すべての動画がダウンロードされる前から、再生されているところです。簡易的なストリーミングできています。
これに対応したmp4を作成するには、プログレッシブダウンロードに対応させる必要があります。
以下のコマンドで
参考: プログレッシブダウンロード対応の MP4ファイル を作成する :Tips & FAQ - arbk-works
共有したい画面の人は以下のコマンドをたたきます。
仕組みとしては、
ログをファイルに取れて、Process Substitution
以下がターミナル画面共有のデモです。
魅力は既存のインストールされているであろう
何を解決したいか?
Mac, Windows, Linux, iPhoneやAndroidのスマホ・タブレットとかのデバイス間でデータの転送したいことがあります。SlackとかLineとかSkypeとかAirDropとかあっても
- 送りたい相手と共通して使っているサービスを探す必要とか、
- GUIのソフトウェアのインストールが必要とか、
- AirDropだとApple系OSである必要
すでにたくさんのファイル共有系のサービスがありますが、コマンドを使ったCUIベースにあまり親切な設計なものはあまりないと思います。
そこで、上記の問題を解決するために、以下のようなファイル転送の仕組みを作りました。
-
他デバイス間でデータ転送ができ、 - 別途ソフトウェアのインストール不要で、
- パイプにとても親和性が高くエンジニアフレンドリー
実際の動作
データの送信者も受信者も転送するためにインストールするものはありません。curlコマンドやブラウザなどHTTP通信ができるものがあれば転送できます。
以下のデモでは、
seq 100000
を上のマシンから下のマシンに送っています。これは
seq 100000
以外にもcat
でもls
でもパイプ渡せるあらゆるものが転送できます。例えば、ファイルが送りたいときはcat ファイル名
とします。以下のように、
100MB.dat
をデバイスをまたいで送れます。エンドツーエンドの暗号化なども可能です。
パイプが使えるということは、、圧縮や暗号化など、また2つ組み合わせて圧縮+暗号化すること可能です。
圧縮送信:
cat myfile | gzip | curl -T ...
解凍送信:
curl ... | zcat > myfile
や
暗号化送信(共通鍵):
cat myfile | openssl aes-256-cbc | curl -T ...
復号化受信(共通鍵):
curl ... | openssl aes-256-cbc -d > myfile
暗号化に
gpg
を使ってもいいですし、将来の最新の暗号方式や圧縮方式が出たらそれを使うことも可能です。一時的なファイルも経由せず、時間的にも空間的にも効率が良く、パイプの素晴らしい可能性が発揮できます。
他にもパイプを使った便利なデータ転送を後述します。
最小の転送機能を搭載したWeb Clientでもファイルを送ったり受け取ったりすることが可能です。
IE10やIE11でも動作可能でした。
以下のデモのようにターミナルからブラウザに画像ファイルを送ることも簡単です。
以下のようにブラウザからもファイルを送ることができ、
curl
で受け取れます。まとめると、
- 従来のHTTP通信で転送可能
- 成熟した枯れた技術に支えられている
- データはストリーミングされる
- Unix/Linuxなどのパイプで効率よく転送できる
- サーバーはデータを経由させるだけで保存は一切しない
- Stream APIの力でうまいこと背圧制御とかもされる
GitHubリポジトリ
プロジェクトはPiping Severと呼んでます。デバイス間のデータをネットワーク越しでパイプさせたい思いをこめました。サーバーサイドTypeScriptです。
GitHub: https://github.com/nwtgck/piping-server
サーバー
どこかのサーバーが独占するわけではなく、サーバーは自由にたくさん立てるポリシーです。好きに自分用のサーバーを立ていただければと思います。デモ用にいくつかサーバーを立てました。 1-
https://ppng.ml/ (ConoHa上) -
https://piping.arukascloud.io/ (Arukas上) -
https://pipings.herokuapp.com/ (Heroku上) -
https://piping-92sr2pvuwg14.runkit.sh/ (RunKit上)
その他個人的な運用では、LAN内にPiping Serverを立ててLANではより高速かつ閉じた転送するのに使ってます。主にLAN内ではSSHなどが使えない場合、特にLinux<=>Windowsなどで使ってます。
使い方が忘れたときはGET /helpで簡単にヘルプが確認できます。
$ curl https://ppng.ml/help ヘルプが出力される
- ポータブルなバイナリで起動させたり、
-
docker run
で起動できたり、
データ転送の仕組み
HTTPを使います。また、NAT超え問題を解決するために、サーバーが送信者と受信者の経由役になります。おそらくピアツーピア(P2P)のTURNサーバに似たものだと思います。多くのデバイス・OSでの利用できるようにするためとインストール不要を実現するために、
広く広まっているプロトコルでの通信が不可欠です。そこで通信はHTTP/HTTPSを使います。
CUIからは、
curl
やwget
で簡単にデータを送るもの、受け取るのも可能です。curl
やwget
は最初からインストールされている事が多いです。macOS, Ubuntu, Amazon Linuxなどよく使われているOSには最初から入っています。しかも
curl
は広く使わていて枯れた技術であり、とても信頼できます。HTTPを使っているため、GUIでもブラウザからデータを送ることも受け取ることもです。
ブラウザならMacでもWindowsでもiPhoneやAndroidなどのスマホ・タブレットでも使えます。
送受信は手軽行えるように極限までシンプルしました。
- 送り方は、任意のパスを指定して、POSTかPUTのボディに送りたいデータを付けて送るだけです。
- 受け取り方は、そのパスを指定してGETすればダウンロードできます。
このストリーミングのおかげでUnix/Linuxのパイプと親和性が高く、効率よく、大きなデータの転送が可能になりました。
セキュリティ
セキュリティに関してはデータ転送においてとても重要なところです。まず、HTTPSを使っていれば、クライアント<=>サーバー間は暗号化されます
上記に書いた
openssl ...
やgpg
コマンドなどを使えば、エンドツーエンドの暗号化も可能になり更に安全になります。上で紹介したデモ動画だと、「送信者がPOST/PUTしたあと、、受信者がGET」という順序ですが、「受信者がGET、送信者がPOST/PUT」の順序でも送信できます。後者のほうがよりセキュリティ的には良い思います。
理由としては前者だとの方法だと、送信者が先に送る準備をしてしまうため、真の受信者がGETする前に、他の受信者がそのパスを指定しまうと、データを得れるからです。もちろんパスを十分に推測不能なものにすればいいのですが、その状況を防げるGET firstがより安全です。
パスは早いものが勝ちになるので、以下のように既に受信者がいる場合は拒否されます。たまたま、ぶつかる可能性があるときも先にGETして予約していたほうが、送信者との安全なコネクションがはれると思います。
- GET /mydata => 送信者を待つ
- GET /mydata => 拒否されて接続が切断 (すでに待ち状態の人がいるから)
- POST /mydata => 1の人に転送される
複数人に送信
/mypath?n=3
のように受信者の人数を指定できる機能があります。n
を指定しないときはn=1
になるようになっていて、今まではn=1
で転送されていました。サーバーに保存されないため、一度ストリームが流れてしまうと同じデータを受け取りたい人に送るときの効率が悪いです。それを解決するための機能になってます。
複数人に送るときのセキュリティ
n=3
のときは、4人目が受信しようとした時点で、4人目の接続が拒否され切断されます。つまり、n
を指定しないn=1
のときは2人目受信しようとした時点で2人目の接続が拒否され切断されます。n
を一般化しているだけなので、上記の通りGET firstなコネクションがより安全な転送方法になると思います。
複数人に送る技術的な話
データの元のストリームがあってそれを複数に分配するような仕組みが必要です。イメージ的には以下の図のようになります。----------> HTTP GET 受信者1 | 送信者 HTTP POST ---サーバー-----> HTTP GET 受信者2 | | ... ----------> HTTP GET 受信者N
stream.PassThroughを使って実現が可能です。
StackOverflowに短い例があったので、引用させていただきます。
下の例だと
echo hi user
の出力の文字数をカウントしつつ、出力の文字列自体も表示しています。const spawn = require('child_process').spawn; const PassThrough = require('stream').PassThrough; const a = spawn('echo', ['hi user']); const b = new PassThrough(); const c = new PassThrough(); a.stdout.pipe(b); a.stdout.pipe(c); let count = 0; b.on('data', function (chunk) { count += chunk.length; }); b.on('end', function () { console.log(count); c.pipe(process.stdout); });
出力
8 hi user
new PassThough()
を作って、そのPassThoughを最初に.pipe()させて、もとのストリームではなくPassThoughのメソッドの.on()や.pipe()を使って処理をしているのが分かると思います。HTTPサーバーを作るときの
http.IncomingMessage
やhttp.ServerResponse
でも同じように使えます。実際にPiping ServerでのPassThoughを使っている箇所は以下になります。
https://github.com/nwtgck/piping-server/blob/eb40fe251b2a552348a4f8f8e635529460f2b4fa/src/piping.ts#L299-L362
Piping Serverの立て方
すぐに気軽に立てれるように、いくつかサーバ立てる方法を用意しています。
Herokuに立てる
Herokuに立てる方法についてです。以下のPiping Serverのリポジトリにあ紫色の[Deploy to Heroku]を押すと、手軽にデプロイできます。
GitHub: https://github.com/nwtgck/piping-server
ボータブルなバイナリ実行形式
zeit/pkgを使って、npmで管理されているプロジェクトをポータブルなバイナリしています。node
本体とソースコードを含めることでnode
をインストール不要で動かせるようになっています。以下のコマンドで、ダウンロードして、実行権限を与えて http://localhost:8888にPiping serverが立ち上がります。
wget https://github.com/nwtgck/piping-server-pkg/releases/download/v0.8.4/piping-server-macos chmod +x piping-server-macos ./piping-server-macos --http-port=8888
...-alpine
、...-macos
、...-linux
と...-win.exe
がGitHub releaseにあります。gitのタグがつくとCI上で自動でGitHub releaseビルドしたバイナリをデプロイするように自動化しました。現在はPiping serverと別リポジトリですが、将来はマージされる可能性があります。
Docker
以下のdocker run
で、バックグラウンドで動作しマシンの再起動後も自動起動でhttp://localhost:8888にPiping Serverが立ち上がります。docker run -d --restart=always -p 8888:80 nwtgck/piping-server --http-port=80
Piping serverはデータを保存しないので、
-v
での永続化もデータベースに繋ぐ必要もありません。Docker imageもgitのタグがつくと、Docker automated buildで自動でイメージがビルドされるようになっています。
npm
Piping Serverはnpmのパッケージなので、以下のようにインストールすることができます。インストール
npm install -g piping-server
起動
piping-server --http-port=8888
Docker(bytenode
)
これは実験的なプロジェクトです。bytenodeというJavaScriptをGoogle V8のバイトコードに事前にコンパイルしてそれを実行するプロジェクトがあり、それを利用したDocker imageです。メリットとしてはDocker imageが軽量です。
webpackなどの代替のparcelを使って、bundleして、それをバイトコードしてそれだけでalpineベースのDocker imageに乗せているので、より軽量なイメージになっています。
これも実験的なので別リポジトリです。
https://github.com/nwtgck/bytenode-piping-server
イメージ名以外起動方法が変わりませんが、イメージサイズがより軽量です。
docker run -d 8888:80 nwtgck/bytenode-piping-server --http-port=80
HTTPでのデータ転送の可能性
「HTTPってどこまで大きいファイル送れるの?」 「HTMLとかRESTのAPIサーバーとか小さいデータを返すイメージしかない」という疑問に関してです。Piping serverで無限にデータを送り続ける実験を47日前に開始しました。現在も進行中で、その結果では現在868テラバイトのデータが転送できています。
無限に送るのは単純で
/dev/urandom
をcatしているだけです。無限に送る送信者
cat /dev/urandom | curl -T - localhost:8888/rand
無限に捨てる受信者
curl localhost:8888/rand > /dev/null
curl -T -
とは
この記事でよく登場しているcurl -T - ...
はPUTメソッドで、標準入力(=パイプされたもの)をHTTPのボディにつけて送ってくれるオプションです。-T
==--upload-file
です。-
を使わずにcurl -T ファイルパス ...
の場合は指定されたファイルを送ることができます。PUTではなくPOSTを使いたいときは、以下でもできます。ただPiping ServerではタイプしやすいようにPUTに対応してます。
cat myfile | curl --data-binary @- https://ppng.ml/mydata
パフォーマンス比較 - Go言語との比較
オリジナルの実装がTypeScript/Node.jsです。そこで、Go言語で最小限のPiping Serverを実装して転送速度の比較しました。転送にかかる時間は大きく差があればあるほど、アップロード・ダウンロードともにユーザー体験が損なわれるので、調べました。比較対象としてGoを選んだのは、新しいサービスがGoで書かれていることが多くGoとの比較に興味があったのと、ネイティブな実行形式を作り出せるGoとスクリプト言語のJavaScriptでどれだけ差があるか知りたかったからです。比較と言っても、そこまできっちりしたベンチーマークとかではなく、実際に送ってみて何MB/secか目視で確認する感じです。結果的にはそこまで顕著な差で出なさそうなことが分かりました。動画として結果を記録しました。
TypeScript/Node.js
YouTube: https://youtu.be/ufijpqHlJww
(https://github.com/nwtgck/piping-server)
Go言語
YouTube: https://youtu.be/NuKvDwB9JSU
(https://github.com/nwtgck/go-piping-server)
クライアントは無限に
yes
でy
をlocalhostのPiping Serverに流し込みます。クライアントは送信者と受信者の組が3で、少しずつ増やしていきました。少しずつ増やしていくと、速度が41~42MB/s=> 38MB/s=>32~34MB/s のように変化する感じで、Node.jsもGoも同じだいたい同じくらい速度でした。Node.jsはスクリプト言語ですが、データ転送部分で使ってるReadableStream#pipe()
の裏の実装がC++とかで書かれてて早いのかと勝手に推測してます。C++でのpipeの実装はこれかもしれません -> (node/src/stream_pipe.cc)
パイプを活かした使用例
よく使いそうな例をまとめます。パイプの可能性が発揮できそうな面白いものも後ろの方にまとめました。
gzip圧縮して送る
gzip
, zcat
で圧縮送信、解凍受信可能です。送る
echo hello | gzip | curl -T - https://ppng.ml/mymsg
受けとる
curl https://ppng.ml/mymsg | zcat
暗号化して送る
openssl aes-256-cbc
を使うとパスワードを使って共通鍵暗号方式でエンドツーエンドの暗号化が実現できます。送る
echo hello | openssl aes-256-cbc | curl -T - https://ppng.ml/mymsg
受けとる
curl https://ppng.ml/mymsg | openssl aes-256-cbc -d
ディレクトリを送る
ポイントは、以下のどちらのコマンドも一時ファイルを作らずにストリームでzipやtar.gzを作って、ディレクトリを転送できるところです。zipで送る
zip -q -r - ./mydir | curl -T - https://ppng.ml/mydir.zip
tar.gzで送る
tar zfcp - ./mydir | curl -T - https://ppng.ml/mydir.tar.gz
プログレスバーを出しながら送る
pv
コマンドを使うと進捗のバーが出てくれます。汎用的な方法は、以下のようにパイプとパイプの間に挟むことで進捗がわかります。
... | pv | curl -T - ...
ファイルを送りたいときは、以下のように
cat
の代わりにpv
を使うことでOO/100%の形でバーが見やすくなります。
WindowsでもCUIで転送したい!
PowerShellを使う方法の紹介です。PowerShellは以下のアイコンのやつです。コマンドプロンプトとは別のアプリケーションで、少なくともWindows 10なら標準で入っているはずです。
iwr
コマンド(=Invoke-WebRequest
標準のエイリアスはずです)を使うとある程度curl
の代わりになります。./mydata.datを送る
iwr https://ppng.ml/mydata -InFile ./mydata.dat -Method Post
./mydata.datとしてダウンロード
iwr https://ppng.ml/mydata -OutFile mydata.dat
パイプして送る
cat ./hello.txt | iwr -InFile $_ -Method POST https://ppng.ml/mymsg
PowerShellはWindowsに限ったものではなく、マルチプラットフォームを目指しているようです。
個人的に一番お手軽に試せると思うのがDockerを使った方法です。
以下のコマンドでシェルが立ち上がります。
docker run -it microsoft/powershell
vi系のエディタで送る
viやvimなどのエディタを使って一時ファイルを作らずにPiping Serverに送る方法です。以下のように、
:w !curl -T - ...
で書いている内容を送ることができます。
標準入力をリアルタイムに送る
以下のように、cat | curl -T - ....
を使うと入力の内容が改行ごとに即時送られます。
ハッシュ値を計算しながら送る
送りながらハッシュ値を計算することで、より自信をもってデータを転送できます。これのポイントも同じく、一時ファイルを作らずにストリーミングしながらハッシュ値を計算しているところです。
>(shasum ...)
という記法はProcess Substitutionという機能で、bashやzshなどに搭載されています。ハッシュを計算しながら送る
seq 100000 | tee >(shasum >&2) | curl -T - https://ppng.ml/myseq
ハッシュを計算しながら受けとる
curl https://ppng.ml/myseq | tee >(shasum >&2) > seq.txt
tee
とProcess Substitutionの両方の知識が必要です。標準入力をtee
は与えられたファイルに書き出しつつ、標準出力にも吐き出します。>(shasum >&2)
を使うとshasum
の標準入力の部分がファイルになってくれてるイメージで、以下のようにecho
すると雰囲気がだいたいつかめると思います。$ echo >(shasum >&2) /dev/fd/63
>(shasum >&2)
でshasum
の標準入力へのファイルパスが得られるため、tee
でうまく動くという感じだと理解しています。
動画をストリーミングで見たい
以下のようにmp4の動画をPiping Serverに送って、ブラウザで開けば簡易的なストリーミングで動画が視聴できます。cat ray.mp4 | pv | curl -T - -H 'Content-Type: video/mp4' https://piping.ml/myvide
ポイントは、すべての動画がダウンロードされる前から、再生されているところです。簡易的なストリーミングできています。
これに対応したmp4を作成するには、プログレッシブダウンロードに対応させる必要があります。
以下のコマンドで
input.mp4
からプログレッシブダウンロード対応のoutput.mp4
を生成できます。ffmpeg -i input.mp4 -codec copy -movflags faststart output.mp4
ターミナルの画面を共有する!!
script
コマンドとcurl
があれば、ターミナルの画面共有も可能です!共有したい画面の人は以下のコマンドをたたきます。
画面を共有したい人
script -f >(curl -T - https://ppng.ml/myscript >&/dev/null)
共有された画面を見る人
curl https://ppng.ml/myscript
/myscript
の箇所はは適宜変えて使ってください。仕組みとしては、
script
コマンドというターミナル作業ログをとるコマンドの力です。ログをファイルに取れて、Process Substitution
>(curl -T -)
に向かってログするようにしています。ネットワーク越しにこれをパイプできるPiping serverに渡るため、画面を見る人はただcurl ...
するだけで画面を見ることができます。以下がターミナル画面共有のデモです。
魅力は既存のインストールされているであろう
script
コマンドとcurl
だけでターミナル共有が完結するところです。また、色のついた文字やtop
やsl
など動きが激しい画面もうまく共有できています。/myscript?n=3
などとすれば、3人に画面共有することもできます。-
コマンドで完結するため、広告などでサーバー運営費をまかなえるようなサービスではないので、予告なしにサーバーと止めることがあると思います。サーバーは手軽にたてれるように心がけたので、止まってしまった時はご自身で立ていただければと思います。 ↩
コメント
コメントを投稿