管道执行后只有命令,管道在这些场景中如何工作?

管道执行后只有命令,管道在这些场景中如何工作?

下面两个例子中会发生什么?为什么每个管道中只执行第二个命令?这里的管道是如何工作的?

示例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将文件的内容通过管道输送到命令的输入中。datecat

date命令不关心其标准输入流,并且将忽略到达那里的任何数据。然而,它将产生自己的输出,这是在其标准输出流上进行的。

互联网可见的结果是 的输出cat被忽略并丢弃,而 的输出date显示在终端中(或管道输出所在的任何地方)。

命令的输出实际发生的情况cat是,由于date不会读取它,因此该cat命令暂时被阻止,等待其输出被读取(在成功输出管道缓冲区可以容纳的内容之后;它不知道date永远不会)阅读)。该date命令执行其操作并输出其字符串,然后终止。

此时,当date终止并且标准输入流date关闭时,该cat命令会收到PIPEshell 发出的信号。该信号表明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

相关内容