shell - 即使从外部更改,也要继续写入同一文件[name]

时间:2014-11-20 15:29:23

标签: bash shell stdout

有一个进程,不应该被中断,我需要从中捕获stdout。

  prg > debug.log

我无法完全修改流程输出数据的方式,尽管我可以自由地将其发布包装起来。背景,将输出交给其他命令等,这些都是公平的游戏。这个过程一旦开始,必须运行到时间结束(并且不能被阻止,比如等待一个fifo被清空)。写作速度不是很快,如果超过预定义的大小,文件可以在任意位置剪切。

现在,问题是日志会增长以填充所有可用空间,因此必须轮换,删除/覆盖最旧的实例。现在出现了问题......

如果我这样做

   mv debug.log debug.log.1

debug.log不断增长的同时,文件debug.log.1会永远消失。

如果我这样做

   cp debug.log debug.log.1
   rm debug.log

文件debug.log.1不会增长,但debug.log会永远消失,并且程序的所有连续输出都会丢失。

是否有某种方法可以使stdout重定向的行为与典型的日志写入一样 - 如果文件消失,重命名等,再次创建它?

(这一切都在busybox下工作,因此首选轻量级解决方案。)

2 个答案:

答案 0 :(得分:1)

如果有问题的应用程序保持日志文件一直打开,并且无法被告知关闭并重新打开日志文件(尽可能多的应用程序可以),那么我能想到的唯一选项是截断文件到位

这样的事情:

cp debug.log debug.log.1
: > debug.log

答案 1 :(得分:1)

您可以使用split命令或任何其他重新打开新文件的命令

prg | split --numeric-suffixes --lines=100 debug.log.

原因是,重定向的文件输出被发送到文件句柄,而不是文件名。 因此,该过程必须关闭文件句柄并打开一个新句柄。

如果您愿意,可以使用rotatelogs以Apache HTTPD样式执行此操作:

http://httpd.apache.org/docs/2.2/programs/rotatelogs.html

在bash样式中,您可以使用脚本:

fn='debug.log'
prg | while IFS='' read in; do
    if ...; then # time or number of lines read or filesize or ...
        i=$((i+1))
        mv "$file" "$fn.$i" # rename the file
        > "$file" # make it empty
    fi
    echo "$in" >> "$file" # fill the file again
done