shell - keep writing to the same file[name] even if externally changed

半城伤御伤魂 提交于 2019-12-23 04:51:14

问题


There's a process, which should not be interrupted, and I need to capture the stdout from it.

  prg > debug.log

I can't quite modify the way the process outputs its data, though I'm free to wrap its launch as I see fit. Background, piping the output to other commands, etc, that's all a fair game. The process, once started, must run till the end of times (and can't be blocked, say, waiting for a fifo to be emptied). The writing isn't very fast, and the file can be cut at arbitrary place, if it exceeds predefined size.

Now, the problem is the log would grow to fill all available space, and so it must be rotated, oldest instances deleted/overwritten. And now there's the problem...

If I do

   mv debug.log debug.log.1

the file debug.log vanishes forever while debug.log.1 keeps growing.

If I do

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

the file debug.log.1 doesn't grow, but debug.log vanishes forever, and all consecutive output from the program is lost.

Is there some way to make the stdout redirect behave like typical log writing - if the file vanished, got renamed or such, create it again?

(this is all working under busybox, so lightweight solutions are preferred.)


回答1:


If the application in question holds the log file open all the time and cannot be told to close and re-open the log file (as many applications can) then the only option I can think of is to truncate the file in place.

Something like this:

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



回答2:


You may use the split command or any other command which reopens a new file

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

The reason is, that the redirected file output is sent to a file handle, not the file name. So the process has to close the file handle and open a new one.

You may use rotatelogs to do it in Apache HTTPD style, if you like:

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

In bash style, you can use a script:

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


来源:https://stackoverflow.com/questions/27043327/shell-keep-writing-to-the-same-filename-even-if-externally-changed

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!