Search code examples
unixfile-iosedin-place

Editing a file in-place with SED seems to prevent any further append operations by processes that are already running


I have a log file that is written to by a server. I wrote a bash script to send me an email if there is an error in the server. I would now like to remove the lines containing the errors so I don't keep getting emails. I accomplish this by doing the following:

sed -i "/WARNING/d" logs/console.log

After running sed however, no more changes are written to the log. I'm guessing this is because running sed closes any open file descriptors or something. However, when I edit the file and manually remove the warning lines with vi I don't have this problem.

I have also tried redirecting the server output myself with both '>' and '>>' operators and after editing the file with sed the same thing happens (i.e. they are no longer updated).


Solution

  • When sed rewrites the log file the server process probably gets an IO error and doesn't try to reopen the log file. I don't know if this approach can work out. sed definitely doesn't have flags to tweak the way it rewrites files with the -i flag, and I don't know if the server can be tweaked to be more resilient when appending to the log.

    So your best option might be a different approach: save the timestamp of the last error look for errors after that timestamp. Something like this:

    ts=
    file=console.log
    while :; do
        if test "$ts"; then
            if sed -e "1,/$ts/d" $file | grep -q WARNING; then
                sed -e "1,/$ts/d" $file | sendmail ...
                ts=$(tail -n 1 $file | cut -f1 -d' ')
            fi
        else
            if grep -q WARNING $file; then
                sendmail ... < $file
                ts=$(tail -n 1 $file | cut -f1 -d' ')
            fi
        fi
        sleep 15
    done
    

    This script is just to give you an idea, it can be improved.