我有一个命名管道'timer_fifo',python脚本的stdout被重定向到timer_fifo,而并行另一个shell脚本进程从中读取,处理它然后将其重定向到另一个名为'activity_file'的文件。
Python脚本:
import time
while True:
print(time.strftime('%Y_%m_%d', time.gmtime()))
time.sleep(1)
执行上面的python脚本:
python above_file_name > timer_fifo
Shell脚本:
while true
do
read action <timer_fifo;
echo $action | stdbuf -o0 -e0 -i0 sed -n "s/^\([^[:space:]].*\)/\1 Cinnamon/p" >> activity_file
done
注意:上面的sed命令附加'Cinnamon'并重定向到活动文件,因此如果输入为'2017_02_01',则它变为'2017_02_01 Cinnamon',如果它以空格开头,它也会忽略输入流。
执行上面的shell脚本:
./file_name
一段时间后文件的尾部:
2017_02_01 Cinnamon
2017_02_01 Cinnamon
2017_02_01 Cinnamon
2017_02_01 Cinnamon
2017_02_01 Cinnamon
2017_02_01 Cinnamon
2017_02_01 Cinnamon
但过了一会儿文件的尾巴:
2017_02_01 Cinnamon
2017_02_01 Cinnamon
2017_02_01 Cinnamon
2017_02_01 Cinnamon
017_02_01 Cinnamon
207_20 Cinnamon
270_1 Cinnamon
210_101_2001_20 Cinnamon
2017_02_0 Cinnamon
270_11207_02_01 Cinnamon
107_20 Cinnamon
0020 Cinnamon
如您所见,为什么输出搞砸了? 此外,我可能不止一次执行上述脚本,因此同时写入同一文件的多个进程会导致该排序输出吗?如果是这样,请解释原因?
答案 0 :(得分:0)
如果您只运行程序的一个副本,则所有内容都按顺序到达fifo,缓冲不会影响排序。
如果您正在运行多个程序副本,并且每个程序都在执行自己的stdout缓冲,那么您可能会获得部分行。
我认为这就是你所看到的。
我认为在这种情况下(不完美)解决方案是在print()
和sleep()
之间的python脚本中添加一行,如下所示:
sys.stdout.flush()
这样,每次调用print()
/ flush()
时,很可能会在单个不间断的系统调用中将整行写入fifo。它仍然不确定 - 你不能保证原子性。但实际上,像这样的短字符串将作为单个系统调用。
(您也可以尝试更改sys.stdout
的缓冲,或者使用运行时标志来进行python,但我认为如上所述调用flush()
是最佳方法。)
:当交互式时,标准流是行缓冲的。否则,它们是块缓冲的,就像常规文本文件一样。