最初のデータがパイプに書き込まれます(一貫性があるかどうか)。

最初のデータがパイプに書き込まれます(一貫性があるかどうか)。

このパイプラインがある場合:

echo "bar" | nc localhost 6969 < <(echo "foo")

「foo」は常にTCPソケットの「bar」の前に書き込まれますか?一貫した優先順位はありますか?

答え1

存在する

cmd1 | cmd2

cmd1そして、パイプの書き込み端(またはksh93のソケットペア)に接続されているstdoutと、パイプのもう一方の端に接続されたstdinと並列cmd2に始まります。cmd1cmd2

存在する:

cmd < file

cmdcmdで開かれたstdinから始まりますfile

だからあなたは見ることができます

cmd1 | cmd2 < file

衝突; cmd2stdinがパイプから来ていないcmd1かどうかfile

上記の場合、ほとんどのシェルでは、<fileリダイレクトが完了した後に優先順位が与えられます。後ろに(シェルはパイプ間の2つのプロセスを開始し、それから各コマンド内の独立したリダイレクトを含む各コマンドが説明されています。

これはcmd2、標準入力がありfile、書き込まれるパイプにリーダーがechoない(壊れたパイプ)を意味します。したがって、あなたの場合は決して成功しなくなり、bar他のプロセスがファイルを開いた後に書くと、実行nc中のプロセスがecho bar終了する可能性があります。bar

zshただし、そのオプションがオンの場合multios(デフォルトではオン)、zsh同じファイル記述子(ここでは0、stdin)を2回リダイレクトしようとしていることが検出され、送信された2つのソースからデータをリダイレクトしたいとしますcmd2。だから標準入力cmd2に送るのではなく、実際に内部パイプを起動します。cmd1fileフィーダー両方のソースからデータを読み取り、それを別のパイプを介して順番に転送するプロセスですcmd2

cmd1 < <(cmd2)

これは、名前付きパイプ(または名前付きパイプのように動作するもの)がもうcmd1 < file一方の端で書かれている場合の1つにすぎませんが、それ以外はあまり変わりません。filecmd2

移植可能な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」の前に書かれていると確信しています。

関連情報