在处理命名管道时,fish shell 和 bash 有什么区别?

Mom*_*ain 5 bash named-pipes fish

在fish shell中执行这些命令时

$ mkfifo answer
$ nc -vv -l -k -p 8001 <answer | tee -a answer
Run Code Online (Sandbox Code Playgroud)

命令挂起。
如果我写answer通过echo "" > answer. 然后nc恢复并开始正确收听。
如果与挂起过程相反CTRL-C,则消息如下:

^C<W> fish: An error occurred while redirecting file 'answer'
open: Interrupted system call
Run Code Online (Sandbox Code Playgroud)

另一方面,在 bash 中执行时:

$ mkfifo answer
$ nc -vv -l -k -p 8001 <answer | tee -a answer
Run Code Online (Sandbox Code Playgroud)

该命令不会挂起并直接开始侦听。

Fish 和 bash 中发生了什么不同的情况来解释这种不同的行为?

rid*_*ish 11

主要区别在于,fishfork在父 shell 中之前打开重定向文件,而 bashfork在子进程中在之后打开重定向文件。

当您打开命名管道进行读取时,打开调用将阻塞,直到有相应的写入器为止(反之亦然)。您的管道包含读取器和写入器,但要求相应的打开调用在子进程中并行发生。在文件打开之前,fishnc无法启动,因此会陷入僵局。

一种解决方法是安排子进程自行打开文件,而不是使用重定向。例如,这将避免死锁:

cat answer | nc -vv -k -l -p 8001  | tee -a answer
Run Code Online (Sandbox Code Playgroud)

Fish 之所以如此,是因为它也使用线程,这限制了您在分叉子项中可以执行的操作。