处理命名管道时,fish shell 和 bash 有啥区别?
Posted
技术标签:
【中文标题】处理命名管道时,fish shell 和 bash 有啥区别?【英文标题】:What are the differences between fish shell and bash when handling named pipes?处理命名管道时,fish shell 和 bash 有什么区别? 【发布时间】:2021-09-17 01:49:41 【问题描述】:在fish shell中执行这些命令时
$ mkfifo answer
$ nc -vv -l -k -p 8001 <answer | tee -a answer
命令挂起。
如果我通过echo "" > answer
写信给answer
。然后nc
恢复并开始正确收听。
如果,相反我CTRL-C
挂了进程,下面是留言:
^C<W> fish: An error occurred while redirecting file 'answer'
open: Interrupted system call
另一方面,在 bash 中,执行时:
$ mkfifo answer
$ nc -vv -l -k -p 8001 <answer | tee -a answer
Listening on localhost 8001
命令不挂起并直接开始收听。
fish 和 bash 中发生了什么不同的情况来解释这种不同的行为?
【问题讨论】:
除了荒谬的回答之外,我还要指出您实际上不能依赖 bash 行为;或任何其他 POSIX shell AFAICT。打开 FIFO 进行读取将阻塞,直到进程打开它进行写入。<answer
在 bash 中打开块,但对您来说并不明显,因为它发生在子进程中。
【参考方案1】:
主要区别在于fish在父shell中在fork
之前打开重定向文件,而bash在子进程中在fork
之后打开重定向文件。
当您打开命名管道进行读取时,打开调用将阻塞,直到有相应的写入器(反之亦然)。您的管道同时包含读取器和写入器,但要求相应的打开调用在子进程中并行发生。在鱼中nc
在文件打开之前无法启动,因此会出现死锁。
一种解决方法是安排子进程自行打开文件,而不是使用重定向。例如,这将避免死锁:
cat answer | nc -vv -k -l -p 8001 | tee -a answer
fish 之所以如此,是因为它也使用线程,这限制了您可以在分叉子项中执行的操作。
【讨论】:
以上是关于处理命名管道时,fish shell 和 bash 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
让 fish shell 与 gcloud 命令行工具一起工作?