当bash脚本仍在运行时强制将输出刷新到文件

我有一个小脚本,每天通过crontab使用以下命令调用:

/homedir/MyScript &> some_log.log 

这个方法的问题是some_log.log只是在MyScript完成之后才创build的。 我想在运行的时候把程序的输出清空到文件中,这样我就可以做类似的事情了

 tail -f some_log.log 

并跟踪进度等

bash本身永远不会写任何输出到你的日志文件。 相反,它作为脚本的一部分调用的命令将分别写入输出和刷新,只要他们喜欢它。 所以你的问题是如何强制在bash脚本内的命令刷新,这取决于它们是什么。

我在这里find了一个解决scheme。 使用OP的例子,你基本上运行

stdbuf -oL /homedir/MyScript &> some_log.log

然后缓冲区在每行输出后被刷新。 我经常把它和nohup结合起来,在远程机器上运行长时间的工作。

stdbuf -oL nohup /homedir/MyScript &> some_log.log

这样,您的进程在注销时不会被取消。

script -c <PROGRAM> -f OUTPUT.txt

关键是-f。 引用man脚本:

  -f, --flush Flush output after each write. This is nice for telecooperation: one person does `mkfifo foo; script -f foo', and another can supervise real-time what is being done using `cat foo'. 

在后台运行:

 nohup script -c <PROGRAM> -f OUTPUT.txt 

您可以使用tee写入文件而不需要冲洗。

 /homedir/MyScript 2>&1 | tee some_log.log > /dev/null 

这不是bash的function,因为所有的shell都是打开有问题的文件,然后将文件描述符作为脚本的标准输出。 你需要做的是确保输出比你现在更频繁地从你的脚本刷新。

在Perl中,例如,可以通过设置:

 $| = 1; 

有关更多信息,请参阅perlvar 。

这会有帮助吗?

 tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq 

这将直接显示来自access.log的唯一条目
http://www.pixelbeat.org/programming/stdio_buffering/stdbuf-man.html

这里发现的问题是,你必须等待你的脚本运行的程序完成他们的工作。
如果你的脚本在后台运行程序,你可以尝试更多的东西。

一般来说,在退出之前调用sync允许刷新文件系统缓冲区,并且可以帮助一点点。

如果在脚本中您在后台& )中启动了一些程序,则可以在退出脚本之前等待它们完成。 要了解它如何运作,你可以在下面看到

 #!/bin/bash #... some stuffs ... program_1 & # here you start a program 1 in background PID_PROGRAM_1=${!} # here you remember its PID #... some other stuffs ... program_2 & # here you start a program 2 in background wait ${!} # You wait it finish not really useful here #... some other stuffs ... daemon_1 & # We will not wait it will finish program_3 & # here you start a program 1 in background PID_PROGRAM_3=${!} # here you remember its PID #... last other stuffs ... sync wait $PID_PROGRAM_1 wait $PID_PROGRAM_3 # program 2 is just ended # ... 

由于wait工作以及PID号码,一个懒惰的解决scheme应该是放在脚本的末尾

 for job in `jobs -p` do wait $job done 

如果你运行一些在后台运行的东西,更困难的是你必须search并等待(如果是这样的话)所有进程的结束:例如,如果你运行一个守护进程,可能情况并非如此等待它完成:-)。

注意:

  • 等待$ {!}的意思是“等到最后的后台进程完成” $! 是最后一个后台进程的PID。 因此,在program_2 &之后wait ${!}等于直接执行program_2而不用在后台发送&

  • wait的帮助:

     Syntax wait [n ...] Key n A process ID or a job specification 

缓冲输出取决于你的程序/homedir/MyScript是如何实现的。 如果你发现输出缓冲,你必须强制执行。 例如,如果是python程序,请使用sys.stdout.flush();如果是C程序,请使用fflush(stdout)。

我不知道这是否会起作用,但是如何调用sync

我在使用StartupItems Mac OS X中使用后台进程时遇到了这个问题。 这是我如何解决它:

如果我使用sudo ps aux我可以看到mytool已经启动了。

当Mac OS Xclosures时,我发现(由于缓冲) mytool决不会将输出传输到sed命令。 但是,如果我执行sudo killall mytool ,则mytool会将输出传输到sed命令。 因此,我在Mac OS Xclosures时执行的StartupItems中添加了一个stop事件:

 start) if [ -x /sw/sbin/mytool ]; then # run the daemon ConsoleMessage "Starting mytool" (mytool | sed .... >> myfile.txt) & fi ;; stop) ConsoleMessage "Killing mytool" killall mytool ;; 

以及是否这个redirect是如何工作的。

在你的情况下,你的脚本的输出(意思是脚本已经完成)redirect到该文件。

你想要做的是在脚本中添加这些redirect。