例えば
# this line should output ssh banner
nc localhost 22
# this line should output the same string expect the replacements
nc localhost 22|sed 's/SSH/XXX/g'
nc localhost 22 > foo # after killing the process, I can see the banner in file `foo`
nc localhost 22|sed 's/SSH/XXX/g' > foo # however I see nothing when sed is used
sed
前述のようにパイプnc
出力を使用している場合は、sed
出力をファイルにリダイレクトできません。
また、結果を渡すために他のコマンドも試しました(たとえばgrep
、tr
同じ結果)。
ただし、cat
結果はファイルにパイプすることができます。奇妙な..
nc localhost 22|cat > foo
それでは、なぜこれが起こるのですか?cat
この場合と他のコマンドの違いは何ですか?sed
出力をファイルにどのようにリダイレクトできますかcat
?
答え1
$猫| sed -e 's/foo/bar/' > 出力.txt 金持ち ^C $catoutput.txt 【何もありません】
しかし:
$猫| sed -e 's/foo/bar/' > 出力.txt 金持ち ^D $catoutput.txt バー
ファイルへの書き込み(ターミナルではない)は通常、Cライブラリ(stdio関数)によって数キロバイト単位でバッファリングされます。パイプを終了するためにCtrl-Cを押すと、sed
パイプが終了する前にバッファを書き込む時間がないため、結果の出力ファイルは空になります。(これは終了シグナルを捕捉できないCライブラリのバグだと言えますが、実際にはそうです。)
Plainはcat
おそらくラインのような複雑なものを処理しないので、stdioを使用しません。そのような部分は異なる場合cat -n
もあれば異なる場合もあります。
パイプを終了するためにCtrl-Cを使用せずに、パイプ自体が完成するように配置できます。少なくとも、nc
この-qN
オプションを使用して、次の後に終了するように指示します。窒素stdinが閉じた後の時間(秒単位)です。たとえば、次のようになります。
$ printf '' | nc -q0 localhost 22 | sed 's/SSH/FOO/' > output.txt
$ cat output.txt
FOO-2.0-OpenSSH_7.4p1 Debian-10+deb9u7
あるいは、バッファリングをオフにする方法は少なくともいくつかあります。 パイプラインでバッファリングをオフにするそして stdoutバッファを削除するには、「unbuffer」または「stdbuf」を使用しますか?
GNU sedに-u
/--unbuffered
スイッチもあります
入力ファイルから最小限のデータをロードし、出力バッファをより頻繁にフラッシュします。