Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 需要解释tee、进程替换、重定向……以及bash和zsh中的不同行为_Linux_Bash_Shell_Zsh_Tee - Fatal编程技术网

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
    two.sh
    的输出与原点“hello”混合并传递到
    third.sh
    ?我希望在stdout中看到1和2的输出,只有
    的“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在这里做了一些非阻塞的事情,并且输出的顺序取决于每个脚本运行的时间。究竟是什么导致了结果
我知道不建议在一篇文章中包含多个问题。然而,所有5个问题都是如此紧密地联系在一起,很可能一个问题的答案也解释了另一个问题。所以我只是在一个帖子里写出来

多谢各位

管道的
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