代码之家  ›  专栏  ›  技术社区  ›  Kent

需要解释tee、进程替换、重定向…以及bash和zsh中的不同行为

  •  0
  • Kent  · 技术社区  · 4 年前

    tee 和过程替代。

    让我们从示例开始:

    $ head *.sh
    

    文件 一.sh

    #!/bin/bash
    echo "one starts"
    if [ -p /dev/stdin ]; then
        echo "$(cat /dev/stdin) from one"
    else
        echo "no stdin"
    fi
    

    二.sh

    #!/bin/bash
    echo "two starts"
    if [ -p /dev/stdin ]; then
        echo "$(cat /dev/stdin) from two"
    else
        echo "no stdin"
    fi
    

    文件

    #!/bin/bash
    echo "three starts"
    if [ -p /dev/stdin ]; then
        sed 's/^/stdin for three: /' /dev/stdin
    else
        echo "no stdin"
    fi
    
    • 从中读取所有三个脚本 standard input 然后打印到 standard output .
    • 这个 one.sh two.sh 非常相似,但 three.sh 有点不同。它只是添加了一些前缀来显示它从标准输入中读取的内容。

    1: echo "hello" | tee >(./one.sh) >(./two.sh) | ./three.sh

    2: echo "hello" | tee >(./one.sh) >(./two.sh) >(./three.sh) >/dev/null

    zsh ).

    Bash(GNU Bash,版本5.0.17(1))

    $ echo "hello" | tee >(./one.sh) >(./two.sh) |./three.sh
    
    three starts
    stdin for three: hello
    stdin for three: one starts
    stdin for three: two starts
    stdin for three: hello from two
    stdin for three: hello from one
    
    • 一.sh 二.sh 混合源代码“hello”并传递给 ? 我希望在标准输出中看到1和2的输出,只有 "hello" .

    $ 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)
    
    • 我将所有标准输出重定向到 /偏差/空
    • 为什么命令按顺序一开始->二->三个,但输出为3->2->1.即使我添加了 sleep 3 在里面 ,

    两个命令,

    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
    
    • 它按预期工作。 但输出的顺序是随机的
    0 回复  |  直到 3 年前
        1
  •  1
  •   Shawn    3 年前
    echo "hello"|tee >(./one.sh) >(./two.sh) |./three.sh
    

    有两种可能的操作顺序 tee 部分管道

    第一

    1. ./three.sh 的标准输入。
    2. 为命令替换设置管道和子进程。它们继承的重定向标准输出管道与 球座 .
    3. 球座 .

    1. 为命令替换设置管道和子进程。它们共享相同的默认标准输出-到终端。
    2. 重新使用 /三.sh
    3. 处决 球座

    bash 使用第一组操作, zsh 使用第二个。在这两种情况下,您在中看到shell脚本输出的顺序由操作系统的进程调度器控制,也可能是随机的。如果您重定向 的标准输出到 /dev/null ,它们似乎都遵循第二种场景,并在父进程之前设置子进程 的重定向。此不一致 猛击 的部分看起来确实很不寻常,而且可能会产生一些微妙的错误。