writer进程退出后如何从命名管道读取?

writer进程退出后如何从命名管道读取?

我想使用命名管道作为异步任务队列(也许类似于 JMS)。

例如,假设客户端发送了一些我希望插入到数据库中的数据,但我希望客户端立即与服务器断开连接,并且服务器进程将数据通过管道传输到命名管道中。然后完全独立地从管道读取数据并执行 SQL 插入,这可能非常慢 - 但客户端不会注意到,因为它立即得到响应。

作为原型,我认为这可行(为了简单起见,“45”是回显的,而不是通过 netcat 客户端-服务器对发送):

zsh> nohup echo "45" > my_named_pipe &
zsh> exit
zsh: warning: 1 jobs SIGHUPed

然后很久以后,执行

zsh> cat my_named_pipe

但管道里什么也没有流出来。我的设置有什么问题吗?

PS:我从来没有nohup工作过。在这种情况下,我总是依赖于disown我不想将其作为单独的命令来执行的操作。

答案1

当你这样做时:

nohup echo "45" > my_named_pipe &

外壳会自行分叉。对于孩子来说,它是my_named_pipe为写作而打开的。这open()会阻塞,直到有其他内容打开my_named_pipe供阅读为止。

当你exit在父进程中运行时,子进程仍然处于阻塞状态open(),尚未执行nohup

因此,退出 shell 后,shell 会向子进程发送 SIGHUP 信号,它不会忽略该信号,因为它尚未运行nohup

赶紧跑:

(echo 45 > my_named_pipe &)

或者与zsh

echo 45 > my_named_pipe &!

&!zsh 是语法糖disown

BASH 和 ZSH 都有一个很好的内置函数,称为 disown。它使用户能够以类似于 nohup 的方式从 shell 中分离进程。 ZSH 有一个很好的糖:你可以放 &!在命令结束时,它将被分离。 BASH没有这样的糖

http://blog.debiania.in.ua/posts/2013-03-13-fun-with-bash-disown.html

答案2

您遇到的问题以及它依赖于 shell 的原因是>首先处理重定向,如果还没有人读取管道,它将阻塞。只有open成功后,shell才会执行nohup。您在它仍处于打开状态时断开连接,因此nohup尚未发生并且SIGHUP杀死了后台进程。这就是为什么disown更好。它立即适用于该工作。

从我尝试用 bash 重现问题来看,bash 似乎不会像 zsh 那样将会话结束的 SIGHUP 转发给它的子进程,因此后台作业仍然存在。

相关内容