将stdout重定向到文件显示错误的内容

时间:2017-02-02 07:13:57

标签: python linux bash shell

我有一个命名管道'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

如您所见,为什么输出搞砸了? 此外,我可能不止一次执行上述脚本,因此同时写入同一文件的多个进程会导致该排序输出吗?如果是这样,请解释原因?

1 个答案:

答案 0 :(得分:0)

如果您只运行程序的一个副本,则所有内容都按顺序到达fifo,缓冲不会影响排序。

如果您正在运行多个程序副本,并且每个程序都在执行自己的stdout缓冲,那么您可能会获得部分行。

我认为这就是你所看到的。

我认为在这种情况下(不完美)解决方案是在print()sleep()之间的python脚本中添加一行,如下所示:

sys.stdout.flush()

这样,每次调用print() / flush()时,很可能会在单个不间断的系统调用中将整行写入fifo。它仍然不确定 - 你不能保证原子性。但实际上,像这样的短字符串将作为单个系统调用。

(您也可以尝试更改sys.stdout的缓冲,或者使用运行时标志来进行python,但我认为如上所述调用flush()是最佳方法。)

来自sys.stdout docs

:当交互式时,标准流是行缓冲的。否则,它们是块缓冲的,就像常规文本文件一样。