第一个数据写入管道(是否一致)

第一个数据写入管道(是否一致)

如果我有这个管道:

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

“foo”总是在“bar”之前写入tcp套接字吗?那里有一致的优先顺序吗?

答案1

cmd1 | cmd2

cmd1和与连接到管道写入端(或 ksh93 中的套接字对)的 stdout 和连接到该管道另一端的 stdincmd2并行启动。cmd1cmd2

在:

cmd < file

cmd是从cmd在 上打开的 stdin开始的file

所以你可以看到

cmd1 | cmd2 < file

冲突;您必须选择cmd2的 stdin 是来自的管道cmd1还是file.

在上面的内容中,在大多数 shell 中,<file重定向完成后 优先(shell 启动 2 个进程,它们之间有管道,并且然后解释每个命令,包括每个命令内独立的重定向)

这意味着cmd2标准输入将是file,并且正在写入的管道echo将没有读取器(损坏的管道)。因此,在您的情况下,bar永远不会成功,并且如果在其他进程打开文件之后写入nc,正在运行的进程echo bar甚至可能会被终止。bar

zsh然而,在打开该选项multios(默认情况下打开)的情况下,zsh检测到您正在尝试重定向同一文件描述符(此处为 0,stdin)两次,并认为您打算将来自这两个源的数据发送到cmd2,因此它实际上会启动一个内部的cmd2管道,而不是将其作为标准cmd1输入file喂食器从两个源读取数据并将其(通过另一个管道一个接一个)发送到 的进程cmd2

cmd1 < <(cmd2)

只是其中的一种情况cmd1 < filefile命名管道(或行为类似于命名管道的东西)cmd2在另一端进行写入,但在其他方面没有太大不同。

可移植的是,如果您想发送两个命令的输出,或者将一个命令的输出和一个文件的内容发送到某个命令,您可以使用:

{
  cmd1
  cmd2
} | cmd3

或者:

{
  cmd1
  cat < file
} | cmd2

所以在这里:

{
  echo bar
  echo foo
} | nc localhost 6969

答案2

echo第一个管道数据的重定向nc被来自进程替换的重定向所覆盖。这意味着nc只会看到来自进程替换的输入,即字符串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 只是将一件事记录到 stdout,然后将 stdin 作为传递发送到 stdout。

在这种情况下,我肯定会假设“foo”总是写在“bar”之前。

相关内容