Bashのネットワーク機能をみんな知るべき (Linuxのテキスト/ファイル転送テクニックレシピ)
Live With Linux::technique
- TOP
- Articles
- Live With Linux
- Bashのネットワーク機能をみんな知るべき (Linuxのテキスト/ファイル転送テクニックレシピ)
序
かなり高い頻度でこの話はしていると思っていたのだが、ChienomiではLinux的にWindowsをバックアップしてみる, 誤家庭のLinuxで大規模ストレージを取り扱う, 新品コンピュータを初期状態に戻せるようにバックアップ, 2000-2005年ころのLinuxとインターネットとパソコンと4回登場しているものの、これ自体を解説した記事がなかったので、書いておく。
これは、概要としては、 “Bashではリダイレクトの特殊な構文としてTCP/UDPによる通信が可能である” ということである。
構文
command > /dev/tcp/host/port
まず、前提として述べておくが、 あくまでCONNECTだけでLISTENはできない。
hostは名前解決の対象になる。
また、仮に全二重でネットワーク接続したとしても、リダイレクトの構文として読み戻すことができないので、あくまでもBashからCONNECTしたら一方的に書き込むか読み出すかのどちらかしかできない。
例
例えばホストserver
で次のようにして待ち受ける。
socat -u TCP-LISTEN:10000 STDOUT
ホストclient
から次のようにする。
echo 'Hello, world!' > /dev/tcp/server/10000
これを利用して、ファイルを転送できる。サーバー側
socat -u TCP-LISTEN:10000 CREATE:somefile
クライアント側
cat somefile > /dev/tcp/server/10000
ファイル群の転送も可能である。サーバー側
socat -u TCP-LISTEN:10000 STDOUT | tar xvf -
クライアント側
tar cvf - . > /dev/tcp/server/10000
あくまでCONNECTであるというだけであり、読み出し側になれないという意味ではない。 だから、Bashのほうでファイルを受け取るようなことも可能だ。 サーバー側
tar cvf - . | socat -u STDIN TCP-LISTEN:10000
クライアント側
tar xvf < /dev/tcp/server/10000
もう少し解説
実際に/dev/tcp
や/dev/udp
というファイルがあるわけではなく、Bashであっても例えば
cat /dev/tcp/server/10000
のようにしても普通にエラーになる。
これは、あくまで「リダイレクト先として/dev/tcp
や/dev/udp
が指定されたときに、Bashが特別な扱いとしてネットワーク通信をする」という仕組みである。
なお、同じようなものとして/dev/fd/n
,
/dev/stdin
, /dev/stdout
,
/dev/stderr
という仮想ファイルが用意されている。UNIXドメインソケットには対応していない。
nc(netcat)とsocat
nc(netcat)は昔からあるネットワーク通信プログラムである。 標準入出力を使ってTCP/UDP/UNIX domain Socketでの通信を行うことができる。
socatはより汎用性を高めた現代的なプログラムである。ファイルデスクリプタ, TCP, UDP, ソケットのほか、ファイル、SCTP, 名前付きパイプ, コマンド, PTY, OpenSSL/TCP/IP, SOCKS4/5などもサポートしており、これらを自由につなぐことができる。HTTPプロキシ経由の接続も可能だ。
以前はnetcatがデフォルトで入っていることが多くて、とりあえずnetcatは使えるケースが多かったのだが、最近のディストリビューションはnetcatも入っていないことが多く、一方socatもnetcatも公式パッケージとして存在することが多いようだ。
このため、使うのであればsocatのほうがお勧めではある。 netcatにまつわる面倒な要素もないし。
ヒント
通信における片側がBashさえあれば良い、ということで、ライブCDなどでブートしてそのままファイル転送に使うことができる。
古いコンピュータなどにおいて古いライブディストリビューションを利用してネットワークファイル転送を行ったり、Windowsでは転送しづらいファイルをWindowsオフラインでバックアップしたい場合などにLinuxによるライブブートで転送するといったことが簡単にできる。
また、netcatやsocatの入っていないLinux環境からネットワーク接続をテストしたり、仮想マシンのホスト/ゲスト間で通信したりするのにも便利。