为啥 bash 在写入命名管道时关闭?
Posted
技术标签:
【中文标题】为啥 bash 在写入命名管道时关闭?【英文标题】:Why bash is closed while writing to named pipe?为什么 bash 在写入命名管道时关闭? 【发布时间】:2016-06-07 07:44:39 【问题描述】:在 bash 1 中:
$ mkfifo /tmp/pipe
$ echo 'something' > /tmp/pipe
现在它挂起并等待读取数据。
在 bash 2 中:
$ </tmp/pipe
现在 shell 1 消失了,它关闭了,我的终端消失了。
为什么会这样?
在bash手册中有写
命令替换 $(cat file) 可以替换为 等效但更快 $(
所以我正在试验普通的“
$ bash --version | head -1
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
$ cat /proc/version
Linux version 3.16.0-71-generic (buildd@lgw01-46) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #92~14.04.1-Ubuntu SMP Thu May 12 23:31:46 UTC 2016
编辑
在看到最初的 cmets 和答案后,我将添加一些说明。
我不关心不同的命令行语法。
但我真正想要的是在阅读器外壳$ < /tmp/pipe
场景中编写器外壳退出,但在阅读器外壳中使用$ cat /tmp/pipe
时,编写器外壳不会退出。为什么?
我发现我真的没有在问题和正文中表达这个问题,应该可能会提出另一个问题?
【问题讨论】:
$(< file)
是命令替换的特例; < file
不是cat file
的通用替代品。
【参考方案1】:
来自the pipe(7)
manual page:
如果引用管道读取端的所有文件描述符都已关闭,则
write(2)
将导致为调用进程生成SIGPIPE
信号。
当读取 shell 完成读取并关闭其管道末端时,写入 shell 将收到SIGPIPE
信号,如果它没有捕获到它,那么 shell 将被终止。
【讨论】:
我不认为他们在问这个问题。我想他们在问为什么如果使用<
而不是cat
,它不会输出任何东西。
@123 问题标题“为什么 bash 在写入命名管道时关闭?”另有说明。
在这种情况下,这是一个明显的重复,应该标记为一个。
这是正确的。如果你做(echo something > /tmp/pipe); echo $?
,你可以看到它。这将打印141
,即128+13
,而13
是SIGPIPE
。所以 subshell 被 SIGPIPE 杀死了。
为什么 "cat /tmp/pipe" 不会导致 SIGPIPE 写入,而 "/pipe" 会?【参考方案2】:
在手动签名中$
与variable
连接而不是command prompt
。
尝试以下脚本:
1)
#!/bin/bash
echo $(< /tmp/pipe);
2)
#!/bin/bash
echo $(cat /tmp/pipe);
两者都能正常工作。
【讨论】:
他没有输入$
,他只是将其显示为命令提示符。
是的。我的意思是$
在$(< file)
中,而不是在$ </tmp/pipe
中
这与问题有什么关系,这就是为什么echo something > /tmp/pipe
的进程消失了?
我不知道命令< /tmp/pipe
是什么意思,但请解释一下,在文档中有使用$(< /tmp/pipe)
的示例。总结: cat /tmp/pipe - 在屏幕上打印 something
,$(cat /tom/pipe) - 作为命令执行 something
,$(something。在我看来< /tmp/pipe
是不正确的命令。【参考方案3】:
当您键入< /tmp/pipe
时,您会将当前shell 的标准输入连接到命名管道。 bash
的工作原理是不断地从其输入中读取并执行它所读取的命令。
-
在 shell 1 中,
echo something > /tmp/pipe
打开写入管道,写入字符串,然后阻塞,直到有东西读取它。 echo
完成后,它将关闭管道的末端。
< /tmp/pipe
打开管道进行读取,并将其连接到 shell 2 的标准输入。
Shell 2 从管道读取数据(并尝试执行命令)。
回到 shell 1,echo
,在从管道读取第二个 shell 后解除阻塞,完成。管道的写入端关闭。
在管道的写入端关闭的情况下,shell 2 在尝试读取另一个命令时会得到一个SIGPIPE
,然后退出。
(另一种可能性是,如果 shell 2 从管道读取并尝试执行的命令导致错误,则它会退出。)
另一方面,$(< file)
是命令替换的一种特殊情况。当bash
看到这一点时,它只是从file
本身读取,而不是生成cat
进程并捕获其输出。
【讨论】:
Writer shell (1) 在完成 write() 时获得 SIGPIPE。阅读器外壳 (2) 不退出。以上是关于为啥 bash 在写入命名管道时关闭?的主要内容,如果未能解决你的问题,请参考以下文章