bash – 写单线时是回波原子
我目前正在试图得到一个脚本来将其他启动命令的输出正确地写入一个日志文件.脚本将使用echo将自己的消息写入日志文件,并且有一种方法可以从其他程序中管道.
主要的问题是生成输出的程序是在后台启动的,所以我读取的函数可以简洁地写入日志文件.这可能是一个问题吗?回声总是只写一条线,所以不应该很难保证原子性.然而,我已经在谷歌看,我没有找到没有办法确保它实际上是原子的. 以下是当前脚本: LOG_FILE=/path/to/logfile write_log() { echo "$(date +%Y%m%d%H%M%S);$1" >> ${LOG_FILE} } write_output() { while read data; do write_log "Message from SUB process: [ $data ]" done } write_log "Script started" # do some stuff call_complicated_program 2>&1 | write_output & SUB_PID=$! #do some more stuff write_log "Script exiting" wait $SUB_PID 您可以看到,脚本可能会同时写入它自己的以及由于重定向输出.这可能导致文件中的havok吗?
回声只是一个简单的包装器(这是一个简化;请参见下面的gory细节编辑),所以要确定echo是否是原子的,查询写是有用的.从
single UNIX specification:
您可以使用简单的C程序来检查系统上的PIPE_BUF.如果你只是打印一行输出,这不是很长的,它应该是原子的. 这是一个简单的程序来检查PIPE_BUF的值: #include <limits.h> #include <stdio.h> int main(void) { printf("%dn",PIPE_BUF); return 0; } 在Mac OS X上,这给了我512(PIPE_BUF的minimum allowed value).在Linux上,我得到4096.所以如果你的行相当长,请确保你在有问题的系统上检查它. 编辑添加:我决定在Bash中检查the implementation of 使用的缓冲区的大小可能是BUFSIZ,尽管它可能不同;如果使用setbuf显式设置缓冲区,BUFSIZ是默认大小,但是没有可移植的方式来确定实际的缓冲区大小.对于什么BUFSIZ也没有便携式指南,但是当我在Mac OS X和Linux上测试时,它是PIPE_BUF的两倍. 这是什么意思?由于回声的输出全部被缓冲,所以在缓冲区被填充或调用fflush之前,它不会实际调用写操作.在这一点上,输出应该写成,上面提到的原子性保证应该适用.如果stdout缓冲区大小大于PIPE_BUF,则PIPE_BUF将是可以写出的最小原子单位.如果PIPE_BUF大于stdout缓冲区大小,那么当缓冲区填满时,流将写入缓冲区. 因此,只能保证回波原子写入比PIPE_BUF中较小的序列和最可能为BUFSIZ的stdout缓冲区的大小.在大多数系统上,BUFSIZ比PIPE_BUF大. tl; dr:echo将原子输出行,只要这些行足够短.在现代系统中,您可能最多可以安装512个字节,但是无法可靠地确定限制. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |