Bash 两个区块之间的管道操作员

Bash 两个区块之间的管道操作员,bash,Bash,我发现了一个有趣的bash脚本,经过一些修改可能会解决我的用例。但我不确定我是否了解它是如何工作的,尤其是街区之间的管道 这两个模块是如何一起工作的?将它们分开的管道的行为是什么 function isTomcatUp { # Use FIFO pipeline to check catalina.out for server startup notification rather than # ping with an HTTP request. This was recom

我发现了一个有趣的bash脚本,经过一些修改可能会解决我的用例。但我不确定我是否了解它是如何工作的,尤其是街区之间的管道

这两个模块是如何一起工作的?将它们分开的管道的行为是什么

function isTomcatUp {

    # Use FIFO pipeline to check catalina.out for server startup notification rather than
    # ping with an HTTP request. This was recommended by ForgeRock (Zoltan).

    FIFO=/tmp/notifytomcatfifo
    mkfifo "${FIFO}" || exit 1
    {
        # run tail in the background so that the shell can
        # kill tail when notified that grep has exited
        tail -f $CATALINA_HOME/logs/catalina.out &
        # remember tail's PID
        TAILPID=$!
        # wait for notification that grep has exited
        read foo <${FIFO}
        # grep has exited, time to go
        kill "${TAILPID}"
    } | {
        grep -m 1 "INFO: Server startup"
        # notify the first pipeline stage that grep is done
        echo >${FIFO}
    }
    # clean up
    rm "${FIFO}"
}
代码源:

bash有一整套复合命令,其工作原理与简单命令非常相似。这里最相关的是每个复合命令都有自己的标准输入和标准输出

{…}就是这样一个复合命令。组内的每个命令都从组继承其标准输入和输出,因此效果是组的标准输出是其子级标准输出的串联。同样,内部的每个命令依次读取组的标准输入。在您的示例中,没有发生任何有趣的事情,因为grep使用所有标准输入,并且没有其他命令尝试从中读取。但是考虑这个例子:

$ cat tmp.txt
foo
bar
$ { read a; read b; echo "$b then $a"; } < tmp.txt
bar then foo
其中a和b都包含foo,因为每个read命令都会重新打开tmp.txt,并且都会读取第一行。

bash有一整套复合命令,它们的工作方式与简单命令非常相似。这里最相关的是每个复合命令都有自己的标准输入和标准输出

{…}就是这样一个复合命令。组内的每个命令都从组继承其标准输入和输出,因此效果是组的标准输出是其子级标准输出的串联。同样,内部的每个命令依次读取组的标准输入。在您的示例中,没有发生任何有趣的事情,因为grep使用所有标准输入,并且没有其他命令尝试从中读取。但是考虑这个例子:

$ cat tmp.txt
foo
bar
$ { read a; read b; echo "$b then $a"; } < tmp.txt
bar then foo
其中a和b都将包含foo,因为每个read命令都将重新打开tmp.txt,并且都将读取第一行。

执行{…;}操作,以便I/O重定向应用于其中的所有命令。{必须像命令名一样分开;}前面必须有分号或换行符,并且也必须分开。这些命令不是在子shell中执行的,这与…不同,后者也有一些语法上的差异

在脚本中,有两个这样的分组通过管道连接。由于管道的原因,每个组都位于一个子壳中,但由于支撑的原因,它不在子壳中

第一组在后台的文件上运行tail-f,然后等待FIFO关闭,这样就可以杀死tail-f。第二部分查找某些特定信息的第一次出现,当它找到它时,停止读取并写入FIFO以释放所有信息

与任何管道一样,退出状态是最后一个组的状态-可能是0,因为回显成功。

执行{…;}操作,使I/O重定向应用于其中的所有命令。{必须像命令名一样分开;}前面必须有分号或换行符,并且也必须分开。这些命令不是在子shell中执行的,这与…不同,后者也有一些语法上的差异

在脚本中,有两个这样的分组通过管道连接。由于管道的原因,每个组都位于一个子壳中,但由于支撑的原因,它不在子壳中

第一组在后台的文件上运行tail-f,然后等待FIFO关闭,这样就可以杀死tail-f。第二部分查找某些特定信息的第一次出现,当它找到它时,停止读取并写入FIFO以释放所有信息


与任何管道一样,退出状态是最后一个组的状态-这可能是0,因为回显成功。

因此,如果grep未能找到匹配项,退出失败,是否意味着FIFO将不会写入,因此将保持打开状态?这是否与块的“单元”执行有关?否。grep的退出状态将丢失,并且尝试写入FIFO的操作将发生。管道的该部分的退出状态将是echo的退出状态,如果成功则为零,否则为非零。请注意,从FIFO读取的代码将被挂起,直到某个进程打开它进行写入,反之亦然。我现在就知道了,感谢您的详细回答:因此,如果grep未能找到匹配项,退出失败,是否意味着FIFO将不会被写入,因此将保持打开状态?这是否与块的“单元”执行有关?否。grep的退出状态将丢失,并且尝试写入FIFO的操作将发生。管道的该部分的退出状态将是echo的退出状态,如果成功则为零,否则为非零。请注意,从FIFO读取的代码将被挂起,直到某个进程打开它进行写入,反之亦然。我现在就知道了,感谢您的详细回复: