Linux 需要解释tee、进程替换、重定向……以及bash和zsh中的不同行为
最近在我的工作中,我遇到了一个关于Linux 需要解释tee、进程替换、重定向……以及bash和zsh中的不同行为,linux,bash,shell,zsh,tee,Linux,Bash,Shell,Zsh,Tee,最近在我的工作中,我遇到了一个关于tee和进程替换的有趣问题,我知道这里有人可以向我解释为什么它是这样工作的 因此,让我们从示例开始: 我有三个小脚本: $ head *.sh ==> one.sh <== #!/bin/bash echo "one starts" if [ -p /dev/stdin ]; then echo "$(cat /dev/stdin) from one" else echo "no st
tee
和进程替换的有趣问题,我知道这里有人可以向我解释为什么它是这样工作的
因此,让我们从示例开始:
我有三个小脚本:
$ head *.sh
==> one.sh <==
#!/bin/bash
echo "one starts"
if [ -p /dev/stdin ]; then
echo "$(cat /dev/stdin) from one"
else
echo "no stdin"
fi
==> two.sh <==
#!/bin/bash
echo "two starts"
if [ -p /dev/stdin ]; then
echo "$(cat /dev/stdin) from two"
else
echo "no stdin"
fi
==> three.sh <==
#!/bin/bash
echo "three starts"
if [ -p /dev/stdin ]; then
sed 's/^/stdin for three: /' /dev/stdin
else
echo "no stdin"
fi
- Q1:为什么
和one.sh
的输出与原点“hello”混合并传递到two.sh
?我希望在stdout中看到1和2的输出,只有third.sh
会传递到的“hello”
three.sh
$ echo "hello" | tee >(./one.sh) >(./two.sh) >(./three.sh) >/dev/null
one starts
two starts
three starts
stdin for three: hello
hello from two
hello from one
<---!!!note here I don't have prompt unless I press Enter or Ctrl-c)
给出预期结果:
one starts
three starts
two starts
hello from two
hello from one
stdin for three: hello
- Q5它按预期工作但是输出的顺序是随机的,似乎zsh在这里做了一些非阻塞的事情,并且输出的顺序取决于每个脚本运行的时间。究竟是什么导致了结果
tee
部分有两种可能的操作顺序
弗斯特
/three.sh
标准输入的管道tee
使用的相同重定向标准输出管道tee
tee
的标准输出重定向到连接到/three.sh
标准输入的管道。此重定向不会影响在步骤1中设置的管道tee
bash
使用第一组操作,zsh
使用第二组操作。在这两种情况下,您在中看到shell脚本输出的顺序由操作系统的进程调度器控制,也可能是随机的。在将tee
的标准输出重定向到/dev/null
的情况下,它们似乎都遵循第二种场景,并在父tee
重定向之前设置子流程。bash部分的这种不一致性看起来确实很不寻常,而且可能会导致一些微妙的错误
我无法复制丢失的提示问题,但这是使用
bash
4.4.20-我没有在这台计算机上安装5。谢谢(最多+1)。你的第一个和第二个回答了我的问题1和问题2。然而,关于输出顺序,在Zsh中,我可以看到输出是随机顺序的。但是在Bash中,无论我如何在这些脚本中添加sleep
,进程都是按照1-2-3
的顺序开始的(我们可以看到xxx开始了
),但是读取stdin和输出到stdout部分的顺序始终是:3-2-1
,2.sh
等待3.sh
完成,然后从/dev/stdin
读取脚本并在Bash中进行一些测试,看看是否可以以不同的顺序进行输出?谢谢。@Kent睡了三个小时。嘘,我得到了XXX开始行的随机顺序,但是是的,剩下的是三二一。是的,这就是我不明白的。xxx的启动
显然取决于我们把睡眠
放在哪里。这不是问题。但我想知道的是stdin阻塞在这里的原因和工作方式。@Kent我还没有查看源代码,但我打赌tee
按与它们在命令行上的显示相反的顺序写入其参数(从右到左),调度器恰好在每次写入后立即运行阻塞等待输入的进程。为什么在它睡觉的时候写到三个街区,现在。。。(编辑:或不编辑。使用read
而不是cat
会导致随机输出顺序)关于tee
的参数处理,我阅读了tee的src,我不太擅长C,但tee似乎按以下顺序提供参数:stdout->file1->file2….fileN
不了解输入从右向左写入的原因:(依我看,它们是完全不同的,值得单独讨论。因此,你真的应该提出不同的问题。
$ echo "hello" | tee >(./one.sh) >(./two.sh) >(./three.sh) >/dev/null
$ echo "hello" | tee >(./one.sh) >(./two.sh) |./three.sh
one starts
three starts
two starts
hello from two
hello from one
stdin for three: hello
echo "hello"|tee >(./one.sh) >(./two.sh) |./three.sh