我有一个简单的 Python 脚本:
#!/usr/bin/python
import os, sys
sys.stderr.write('I am %s' % os.getpid())
sys.stderr.flush()
print "hello"
sys.stderr.write('I am done')
当我从 Bash 运行此脚本并将标准输出重定向到 FIFO 时:
$ mkfifo fifo
$ /pyscript > fifo
奇怪的是,在我从 FIFO 读取之前:
我不会收到“我是(PID)”消息,
我看不到使用的脚本
ps -ef
并使用拉索夫,我看不到有人拥有先进先出文件打开!
一旦我从 FIFO 中读取数据,我正在写入 stderr 的两条消息就会立即出现。
怎么了?
背景:我正在编写一个测试,在其中创建 FIFO 并向其写入“hello”;然后我运行测试并期望 SUT不是从中读取; IE。忽略该文件即可。我尝试这样做,mkfifo test_fifo; /bin/echo hello > test_fifo &; run_the_test; killall echo
但令我惊讶的是,这个echo
过程从未存在过!在这样的测试之后我应该如何“清理”(除了rm test_fifo
)......?
答案1
在成功完成任何文件重定向之前,shell 不会运行程序。该命令pyscript > fifo
将导致 shell 分叉,然后尝试打开fifo
.仅当某些进程已打开fifo
以供读取时,此操作才会成功。在此之前,子 shell 将处于管道等待状态。
$ (sleep 10;ps -l -t pts/0)&
[1] 2574
$ pyscript > fifo
F S UID PID PPID WCHAN TTY CMD
0 S 1000 2554 2535 wait pts/0 bash //interactive shell
1 S 1000 2574 2554 wait pts/0 bash //fork of shell, parent of sleep and ps
1 S 1000 2576 2554 pipe_w pts/0 bash //fork of shell, waiting to open fifo
0 R 1000 2577 2574 - pts/0 ps
答案2
管道或 FIFO 的两端必须同时打开。如果您从没有任何进程写入的管道或 FIFO 文件中读取数据(可能是因为它们都已关闭文件或退出),则读取将返回文件结尾。写入没有读取过程的管道或 FIFO 将被视为错误条件;它会生成 SIGPIPE 信号,如果该信号被处理或阻止,则会失败并显示错误代码 EPIPE。
http://www.gnu.org/software/libc/manual/html_node/Pipes-and-FIFOs.html