3

基本上我想了解这些命令之间的区别:

cat <<< yolo | tee f.txt
echo yolo | tee t.txt

还有那些命令:

cat <<< yolo > >(tee f.txt)
echo yolo > >(tee t.txt)

前两个命令的结果完全相同:打印“yolo”,然后终端返回控制权,这正是我所期望的。

[user@localhost ~]$ cat <<< yolo | 三通 f.txt

约洛

[user@localhost ~]$ echo yolo | 三通.txt

约洛

但是使用进程替换,会发生一些奇怪的事情echo

[user@localhost ~]$ cat <<< yolo >>(tee f.txt)

约洛

[user@localhost ~]$ echo yolo > >(tee t.txt)

[user@localhost ~]$ yolo

在打印出文本之前,终端会返回控制权。在这种情况下,为什么我能更快地获得控制权?

这一定与如何打开进程以及如何在进程之间传递文件描述符有关,但我有点达到了我的知识极限。

如果我将它通过管道传输到其他任何东西,一切都会恢复正常,例如echo yolo > >(tee t.txt) | cat.

更奇怪的是 xargs'ing intoecho效果很好:

[user@localhost ~]$ xargs echo <<< yolo >>(tee t.txt)

约洛

但你可以说这xargs是这里的主程序,而不是echo.

如果我使用输入过程替换,cat我会得到不同的结果:

cat < <(echo yolo) > >(tee t.txt)

有时它给了我这个:

[user@localhost ~]$ cat <<(echo yolo) > >(tee t.txt)

[user@localhost ~]$ yolo

有时是这样的:

[user@localhost ~]$ cat <<(echo yolo) > >(tee t.txt)

约洛

所以我想这可能与系统执行命令的速度有关,这使得它变得不可预测。

这是否意味着输出进程替换(例如tee在本例中)在后台运行?

4

1 回答 1

2

啊,我好像找到……

进程替换...进程异步list运行,其输入或输出显示为文件名...

一旦命令(或分叉进程完成),控制权将返回到终端并显示下一个提示。我最初怀疑echo内置可能起到了作用,但它实际上只是扭曲了时间。即一旦使用> >(tee t.txt)when 确实tee打印到控制台并不是完全确定的。

就此而言,试试这个(对于你的第三个例子):

$ cat <<< yolo > >(sleep 1; tee f.txt)
$ yolo

相对于:

$ { echo yolo; sleep 1 ;} > >(tee t.txt)
yolo
$

不同之处在于>(list)进程替换是如前所述异步执行的。尝试两个示例中的前一个,即使使用更大的值sleep来模拟长时间运行的过程。当你继续使用你的 shell 时它会一直存在(实际上即使你终止它,在这种情况下它会被重新设置,但你仍然会在进程列表中看到;旁注:“命令作为命令的结果运行替换忽略键盘生成的作业控制信号SIGTTIN,SIGTTOUSIGTSTP.”& -> 与下面的异步 ( ) 执行示例不同,即使丢失终端也不会杀死它们。

另一方面,管道:

如果管道不是异步执行的(参见列表),shell 将等待管道中的所有命令完成。

在管道中的所有命令执行完毕之前,Shell 不会恢复控制(下一个命令不会执行)。

尝试:

$ echo yolo |  (sleep 1; tee f.txt)
yolo
$

与(类似于 using >(list))相反:

echo yolo |  ((sleep 1; tee f.txt) &)
$ yolo

(实际上并不需要双子外壳,我只是用它来抑制正在运行的外壳中的作业控制消息)。

于 2020-02-25T13:23:39.140 回答