'cmd1 | 之间的区别cmd2' 和 'cmd2 foo; cmd2 foo'?

'cmd1 | 之间的区别cmd2' 和 'cmd2 foo; cmd2 foo'?

或者:当 cmd2 可以使用两者并且是单个命令时,什么时候以及为什么不喜欢 STDIN?

我在这个网站上遇到了一些问题,其中 3 个答案是上述每个问题之一,例如这个。这个问题有第一个答案变体mkfifo foo; cmd2 foo; cmd2<foo

对我来说,相关的 3 个答案读起来都像是功能重复,但底层语义略有不同。每当我看到这一点时,我就想知道后两个答案是否应该对第一个答案进行编辑,或者到目前为止我是否还没有意识到一些真正重要的东西。

以下是具体示例(关于“使用本地wireshark通过ssh嗅探远程网络设备”):

与先进先出,原答案(1)

$ mkfifo /tmp/remote; wireshark -k -i /tmp/remote
$ ssh remote "tcpdump -s 0 -U -n -w - <moreOpts>" > /tmp/remote

回答(2) with <(...)(过程替换)

$ wireshark -k -i <(ssh remote tcpdump -s0 -U -n -w - <moreOpts>)

回答(3)、带|(管道)

$ ssh remote tcpdump -U -n -s0 <moreOpts> -w - | wireshark -k -i -

我自己通常会选择cmd1 | cmd2我的案例的版本,因为我也发现它更容易按顺序阅读。

从来没有理由深入挖掘细节,但我隐约记得一些关于变量、范围、子 shell 缓冲的边缘情况。

那么,当我应该(不)使用形式 1、2 或 3 时,边缘情况是什么?

(1) 的一个例子是,如果 ssh 链接不稳定,则可以单独重新启动进程。但除此之外,我没有看到/发现任何关于何时不喜欢类型管道的硬性规则。

答案1

主要区别在于各种命令在哪个 shell 中运行。无论如何,由于sshwireshark都是外部进程,因此在语义上使用哪一个几乎没有什么区别。

如果一个或两个命令都是 shell 命令,则差异更为相关。使用 时mkfifo,这两个命令都在当前 shell 实例中运行。使用管道,这两个命令都在从调用 shell 派生的子 shell 中运行。使用进程替换 ( <(...)),wireshark由当前 shell 启动,但ssh在子 shell 中启动。

这可能会影响变量更改的处理方式。考虑:

  1. x=0; echo foo | { x=1; cat; }; echo "$x"输出 0 的值x
  2. x=0; { x=1; cat; } < <(echo foo); echo "$x"输出值为 1x

对于你的情况,我会使用简单的管道;不需要非标准扩展,例如进程替换。

ssh remote tcpdump -U -n -s0 <moreOpts> -w - | wireshark -k -i -

相关内容