简体   繁体   English

将标准输出重定向到文件显示错误的内容

[英]Redirecting stdout to file shows wrong content

I have a named pipe 'timer_fifo', stdout of a python script is redirected to timer_fifo while parallely another shell script process reads from it, processes it then redirects it to another file named 'activity_file'. 我有一个命名管道'timer_fifo',python脚本的stdout重定向到timer_fifo,与此同时,另一个shell脚本进程从中读取了它,对其进行处理,然后将其重定向到另一个名为'activity_file'的文件。

Python Script: Python脚本:

import time
while True:
    print(time.strftime('%Y_%m_%d', time.gmtime()))
    time.sleep(1)

Executing above python script: 执行以上python脚本:

python above_file_name > timer_fifo

Shell script: Shell脚本:

while true
do
    read action <timer_fifo;
    echo $action | stdbuf -o0 -e0 -i0 sed -n "s/^\([^[:space:]].*\)/\1 Cinnamon/p" >> activity_file
done

Note: Above sed command appends 'Cinnamon' and redirects to activity file, so if input is '2017_02_01' then it becomes '2017_02_01 Cinnamon', also it ignores the input stream if it starts with space. 注意:上面的sed命令追加了'Cinnamon'并重定向到活动文件,因此,如果输入为'2017_02_01',则其变为'2017_02_01 Cinnamon',并且如果输入流以空格开头,它将忽略输入流。

Executing above shell script: 执行上面的shell脚本:

./file_name

for some time the tail of file: 在一段时间的文件尾:

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

But after a while the tail of file: 但是过了一会儿文件的尾巴:

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

As you see, why is the output messed up? 如您所见,为什么输出混乱了? Also I may have executed the above scripts more than once, so will multiple processes writing simultaneously to same file cause that sort output? 另外,我可能已经多次执行了上述脚本,所以同时写入同一文件的多个进程会导致这种输出吗? If so please explain why? 如果是这样,请解释原因?

If you're only running one copy of your program, then everything is arriving in the fifo in sequence, and buffering does not affect ordering. 如果您仅运行程序的一个副本,则所有内容均按顺序到达fifo,并且缓冲不会影响顺序。

If you're running more than one copy of your program, and they're each doing their own buffering of stdout, then you could get partial lines. 如果您正在运行一个以上的程序副本,并且每个程序都在各自执行stdout的缓冲,那么您可能会得到部分行。

I think that's what you're seeing. 我认为这就是您所看到的。

I think the (imperfect) solution in this case is to add a line in your python script between the print() and the sleep() as follows: 我认为在这种情况下,(不完美的)解决方案是在python脚本中的print()sleep()之间添加一行,如下所示:

sys.stdout.flush()

This will make it very likely that whole lines will get written to the fifo in single, uninterrupted system calls, every time print() / flush() are called. 每次调用print() / flush() ,很可能在不中断的单个系统调用中将整行写入到fifo中。 It still won't be certain--you get no guarantees about atomicity. 仍然不确定-您无法保证原子性。 But in practice, short strings like this will go as single system calls. 但实际上,这样的短字符串将作为单个系统调用使用。

(You could also try changing sys.stdout 's buffering, or use a runtime flag to python, but I think calling flush() as above is the best approach.) (您也可以尝试更改sys.stdout的缓冲,或对Python使用运行时标志,但我认为如上所述调用flush()是最好的方法。)

from sys.stdout docs : When interactive, standard streams are line-buffered. 来自sys.stdout docs :交互式时,标准流是行缓冲的。 Otherwise, they are block-buffered like regular text files. 否则, 它们将像常规文本文件一样被块缓冲

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM