このパイプラインがある場合:
echo "bar" | nc localhost 6969 < <(echo "foo")
「foo」は常にTCPソケットの「bar」の前に書き込まれますか?一貫した優先順位はありますか?
答え1
存在する
cmd1 | cmd2
cmd1
そして、パイプの書き込み端(またはksh93のソケットペア)に接続されているstdoutと、パイプのもう一方の端に接続されたstdinと並列cmd2
に始まります。cmd1
cmd2
存在する:
cmd < file
cmd
cmd
で開かれたstdinから始まりますfile
。
だからあなたは見ることができます
cmd1 | cmd2 < file
衝突; cmd2
stdinがパイプから来ていないcmd1
かどうかfile
。
上記の場合、ほとんどのシェルでは、<file
リダイレクトが完了した後に優先順位が与えられます。後ろに(シェルはパイプ間の2つのプロセスを開始し、それから各コマンド内の独立したリダイレクトを含む各コマンドが説明されています。
これはcmd2
、標準入力がありfile
、書き込まれるパイプにリーダーがecho
ない(壊れたパイプ)を意味します。したがって、あなたの場合は決して成功しなくなり、bar
他のプロセスがファイルを開いた後に書くと、実行nc
中のプロセスがecho bar
終了する可能性があります。bar
zsh
ただし、そのオプションがオンの場合multios
(デフォルトではオン)、zsh
同じファイル記述子(ここでは0、stdin)を2回リダイレクトしようとしていることが検出され、送信された2つのソースからデータをリダイレクトしたいとしますcmd2
。だから標準入力cmd2
に送るのではなく、実際に内部パイプを起動します。cmd1
file
フィーダー両方のソースからデータを読み取り、それを別のパイプを介して順番に転送するプロセスですcmd2
。
cmd1 < <(cmd2)
これは、名前付きパイプ(または名前付きパイプのように動作するもの)がもうcmd1 < file
一方の端で書かれている場合の1つにすぎませんが、それ以外はあまり変わりません。file
cmd2
移植可能な2つのコマンドの出力、または1つのコマンドの出力とファイルの内容をコマンドに送信するには、次のようにします。
{
cmd1
cmd2
} | cmd3
または:
{
cmd1
cat < file
} | cmd2
だからここにあります:
{
echo bar
echo foo
} | nc localhost 6969
答え2
echo
最初のパイプラインデータのリダイレクトは、nc
プロセス交換のリダイレクトで上書きされます。つまり、nc
プロセス置換の入力のみが表示されます(例:strings)foo
。
より一般的には、
command1 | command2 <data
command2
未読出力ですcommand1
。
両方の文字列を読むためにnc
一緒に渡す準備をするか、
{ echo "foo"; echo "bar"; } | nc localhost 6969
または
nc localhost 6969 < <( echo "foo"; echo "bar" )
答え3
え、なんだかトリッキーに見えますね。 Cで何かを書くこともできますが、node.jsを使用するとこの問題を解決できます。
#!/usr/bin/env node
'use strict';
const msg = process.argv[2] || process.env.ql_message;
if(!msg){
console.error('quicklock: no message defined in ql_init_message.');
process.exit(1);
}
console.log(msg);
process.stdin.resume().pipe(process.stdout);
コマンドラインで次のように使用できます。
echo "bar" | initial_message "foo" | nc localhost 6969;
initial_message は 1 つだけを stdout に記録し、stdin を stdout へのパスとして送信します。
この場合、「foo」は常に「bar」の前に書かれていると確信しています。