或者:当 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
$ 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 中运行。无论如何,由于ssh
和wireshark
都是外部进程,因此在语义上使用哪一个几乎没有什么区别。
如果一个或两个命令都是 shell 命令,则差异更为相关。使用 时mkfifo
,这两个命令都在当前 shell 实例中运行。使用管道,这两个命令都在从调用 shell 派生的子 shell 中运行。使用进程替换 ( <(...)
),wireshark
由当前 shell 启动,但ssh
在子 shell 中启动。
这可能会影响变量更改的处理方式。考虑:
x=0; echo foo | { x=1; cat; }; echo "$x"
输出 0 的值x
。x=0; { x=1; cat; } < <(echo foo); echo "$x"
输出值为 1x
对于你的情况,我会使用简单的管道;不需要非标准扩展,例如进程替换。
ssh remote tcpdump -U -n -s0 <moreOpts> -w - | wireshark -k -i -