我有一个命名管道“timer_fifo”,python 脚本的标准输出被重定向到 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
如您所见,为什么输出是乱七八糟的? 另外我可能不止一次执行了上述脚本,那么多个进程同时写入同一个文件会导致排序输出吗?如果是,请解释为什么?
最佳答案
如果您只运行程序的一个副本,那么所有内容都会按顺序到达 fifo,缓冲不会影响顺序。
如果您正在运行程序的多个副本,并且每个副本都在做自己的标准输出缓冲,那么您可能会得到部分行。
我认为这就是您所看到的。
我认为在这种情况下(不完美的)解决方案是在 print()
和 sleep()
之间的 python 脚本中添加一行,如下所示:
sys.stdout.flush()
这将很可能在每次调用 print()
/flush()
时,在单个不间断的系统调用中将整行写入 fifo .它仍然不确定——你无法保证原子性。但在实践中,像这样的短字符串将作为单个系统调用。
(您也可以尝试更改 sys.stdout
的缓冲,或使用 python 的运行时标志,但我认为如上所述调用 flush()
是最好的方法。)
来自 sys.stdout docs :当交互时,标准流是行缓冲的。否则,它们会像普通文本文件一样进行 block 缓冲。
关于python - 将标准输出重定向到文件显示错误内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41996187/