下面两个例子中会发生什么?为什么每个管道中只执行第二个命令?这里的管道是如何工作的?
示例1
$ cat /var/log/messages | date
Mon Apr 8 17:10:02 IST 2019
示例2
$ cat /var/log/messages | w
17:10:34 up 8 days, 1:24, 6 users, load average: 0.63, 0.49, 0.61
答案1
两个示例中的两个命令都是被处决。实际上仅显示管道符号之后的命令输出。
在管道中,通过在管道的左侧运行,/var/log/messages
将文件的内容通过管道输送到命令的输入中。date
cat
该date
命令不关心其标准输入流,并且将忽略到达那里的任何数据。然而,它将产生自己的输出,这是在其标准输出流上进行的。
互联网可见的结果是 的输出cat
被忽略并丢弃,而 的输出date
显示在终端中(或管道输出所在的任何地方)。
命令的输出实际发生的情况cat
是,由于date
不会读取它,因此该cat
命令暂时被阻止,等待其输出被读取(在成功输出管道缓冲区可以容纳的内容之后;它不知道date
永远不会)阅读)。该date
命令执行其操作并输出其字符串,然后终止。
此时,当date
终止并且标准输入流date
关闭时,该cat
命令会收到PIPE
shell 发出的信号。该信号表明cat
它尝试写入其标准输出的任何数据都永远不会被读取,并且它也会终止(终止PIPE
是该信号的默认操作)。正在读取的文件的其余部分cat
永远不会被读取,并且当 shell 释放与其关联的内存时,管道缓冲区中的数据将被丢弃。
date
替换为w
或任何其他不读取其标准输入流的命令也会发生完全相同的情况。
您可以将其与实际使用的命令进行比较做读取其标准输入流:
cat /var/log/messages | tr '[:lower:]' '[:upper:]'
或者,没有管道(因为cat
在任何这些示例中实际上都不需要管道),
tr '[:lower:]' '[:upper:]' </var/log/messages
答案2
这就是管道的工作方式:左侧命令的输出作为输入发送到右侧命令。
如果要依次运行两个命令,请使用分号:
cat /var/log/messages ; date
如果您只想在第一个命令成功后才运行第二个命令,请使用&&
:
cat /var/log/messages && date
如果您只想在第一个命令失败时才运行第二个命令,请使用||
:
cat /var/log/messages || date
如果您想在后台运行第一个命令并同时运行第二个命令,请使用&
cat /var/log/messages & date