nc
OS X Mavericksで、クライアントがソケットを開いたままにし、サーバーがソケットから切断されるまでデータを読み取るようにする方法は?
データをサーバーに送信し、nc
応答を使用してこれを実行したいと思います。問題は、nc
サーバーからの応答を待たずにデータを送信した後にソケットを切断することです。
これによりデータが記録され終了します。
$ echo "my instruction here" | nc 127.0.0.1 $MY_PORT
これにより、データを書き込んだ後にサーバーが切断されても終了しません。
$ cat <(echo "my instruction here") - | nc 127.0.0.1 $MY_PORT
OS X Mavericksのマニュアルページには、リクエストを送信してレスポンスを印刷する次のnc
例HTTP GET
がありますが、機能しません。ただ要求を送信し、サーバーからの応答を待たずに終了します。マニュアルページの情報が間違っていると思いますか?
$ echo -n "GET / HTTP/1.0\r\n\r\n" | nc host.example.com 80
答え1
ncのデフォルトの動作は、stdinが閉じられたときに接続を閉じることです。変更するには、Linuxで-qオプション(たとえば-q -1
)を使用できます。OS Xではおそらく同じです。詳しくはマニュアルページをご覧ください。
編集:OS X ncは-qスイッチなどをサポートしていないようです。この場合、次の手順を実行してstdinが閉じられないようにする必要があります。
(エコ「foo」、睡眠100000)|
答え2
リスニングnc
(サーバー)が閉じると、クライアントnc
も終了します。
Mac OS Xではopen -a 'Activity Monitor'
これを確認できます。
例は中断さnc & cat
れず、nc
読み取りcat
と書き込みのためにstdinとstdoutを開いたままにします。
ただし、cat
リスナーが閉じてパイプに書き込もうとすると、エラーが発生して終了します。nc
SIGPIPE
cat
# cat & SIGPIPE test
(sleep 1; echo hi) |
(trap 'echo "received signal $(($? - 128))" 1>&2' EXIT; cat) | :
kill -l 13
man bash | less -p 'EXIT STATUS'
man bash | less -Ip '128\+n'
Niklas Berglundの回避策のnc
代わりに、中断されたコマンドを含むプロセスグループ全体を終了するためにクライアント出口をキャプチャすることが可能ですcat
。
# console 1
# ctrl-c will "kill 0" entire process group sh -c '...'
nc -l 8080
# console 2
# script command (FreeBSD version) will implicitly run: man 2 setsid
# kill 0 will therefore only kill the entire process group sh -c '...'
# run in a script kill 0 would otherwise kill the entire script
# cf. also https://github.com/jerrykuch/ersatz-setsid
script -q /dev/null sh -c '
(echo "my instruction here"; cat) | (trap "kill 0" EXIT; nc 127.0.0.1 8080)
'
答え3
解決策はソケットに書き込むことです。nc
データを書き込めなくなったら終了します。
(echo -ne "GET / HTTP/1.0\r\n\r\n"; (while true; do echo -e "\n"; sleep 1; done)) | nc example.com 80
nc
nc
ソケットに書き込めないため、終了するまで毎秒空白行を送信しますnc
。
このソリューションを案内してくれたSteffen Ullrichの回答とコメントに感謝します。