IO Redirection in Linux Bash shell scripts not recreating moved/deleted file?

1.2k views Asked by At

I am quite new to shell programming on Linux and in my Linux instance, I am redirecting the stdout and stderr of a program to two files in following manner and run it in background

myprog > run.log 2>> err.log &

This works fine, and I get my desired behavior

Now there is a another background process that monitors the run.log and err.log, and moves them to other file names, if the log files grow beyond a certain threshold.

e.g. mv err.log err[date-time].log

my expectation is that after this file move happens, err.log will be created again by the myprog output redirection and new output will be written to that new file. However, after my log file monitoring process moves the file, err.log or run.log never get created again although myprog continues to run without any issues.

Is this the normal behavior in Linux? If it is, what should I do to get my expected behavior working?

3

There are 3 answers

3
Vitor On BEST ANSWER

Yes, it is. Unless you first program reopen the files, it will keep writing to the old file, even if you can't access it anymore. In fact, the space used by that removed file will only be available after every process closes it. If reopening it is not possible (ie. you can't change the executable nor restart it), then a solution like http://httpd.apache.org/docs/2.4/programs/rotatelogs.html is your best bet. It can rotate logs based on filesize or time, and even call a custom script after a rotation.

Example usage:

myprog | rotatelogs logname.log 50M

This way the log will be rotated whenever the size reaches 50 megabytes.

[EDIT: pointed to a newer version of rotatelogs]

0
Charles Duffy On

Software with support for log rotation actually has support written in for this rotation. If you look at man logrotate, you'll notice that a typical configuration looks like this:

   "/var/log/httpd/access.log" /var/log/httpd/error.log {
       rotate 5
       mail [email protected]
       size 100k
       sharedscripts
       postrotate
           /usr/bin/killall -HUP httpd
       endscript
   }

...which is to say that it sends a HUP signal to the program whose log has been rotated; that program has a signal handler that reopens its output files.


You can do this in your shell scripts too:

reopen_logs() {
  exec >>run.log 2>>err.log
}
trap reopen_logs HUP

...then, after rotating your logs, run kill -HUP pid_of_yourscript; on the next occasion when the script itself is executing a command (since signal handlers only run between foregrounded executables), it will reopen its output to recreate the log file without needing to restart.

3
Ron Thompson On

If I had to guess, it actually associates the process that is logging with a file descriptor, not a file name. When you rename it, you only change the file name. So the process just keeps logging to the file. Just a guess. If I were tasked with fixing it, I would stop the logging process and restart it at that point to re-associate it with the right file.

Just a guess.