I have the following issue:
I have an application, which continuously produces output to stderr and stdout. The output of this application is captured in a logfile (the app is redirected as: &> log.txt
). I don't have any options to produce a proper logging to file for this.
Now, I have a cron job, which runs every hour and beside of doing other things, it also tries to rotate this logfile above, by copying it to log.txt.1 and then creates an empty file and copies it to log.txt
It looks like:
cp log.txt log.txt.1 touch /tmp/empty cp /tmp/empty log.txt
The problem is, that the application is still writing to it, and because of this I get some very strange stuff in the log.txt.1, it starts with a lot of garbage characters, and the actual log file is somewhere at the end.
Do you have any idea, how to make a correct log rotating for this specific situation (I also tried cat log.txt > log.txt.1
, does not work)? Using logrotate
for this specific application not an option, there is a whole mechanism behind the scenes that I may not change.
Thanks, f.
A number of log files are set up for rotation as soon as a Linux system is installed. In addition, certain applications add their own log files and rotation specs when they are installed on the system. The configuration files for log-file rotations can be found in the /etc/logrotate.
System log files are rotated by the logadm command from an entry in the root crontab file.
Tells logrotate which command to use when mailing logs. This command should accept two arguments: 1) the subject of the message, and 2) the recipient. The command must then read a message on standard input and mail it to the recipient. The default mail command is /bin/mail -s.
To write output of Bash Command to Log File, you may use right angle bracket symbol (>) or double right angle symbol (>>). Right angle braketsymbol (>) : is used to write output of a bash command to a disk file. If the file is not already present, it creates one with the name specified.
Okay, here's an idea, inspired by http://en.wikibooks.org/wiki/Bourne_Shell_Scripting/Files_and_streams
make a named pipe:
mkfifo /dev/mypipe
redirect stdout and stderr to the named pipe:
&> /dev/mypipe
read from mypipe into a file:
cat < /dev/mypipe > /var/log/log.txt &
when you need to log-rotate, kill the cat, rotate the log, and restart the cat.
Now, I haven't tested this. Tell us how it goes.
Note: you can give the named pipe any name, like /var/tmp/pipe1 , /var/log/pipe , /tmp/abracadabra , and so on. Just make sure to re-create the pipe after booting before your logging-script runs.
Alternatively, don't use cat, but use a simple script file:
#!/bin/bash while : ; do read line printf "%s\n" "$line" done
This script guarantees an output for every newline read. (cat might not start outputting until its buffer is full or it encounters an EOF)
IMPORTANT NOTE: Please read the comments from @andrew below. There are several situations which you need to be aware of.
Alright! Finally got access to my Linux box. Here's how:
Step 1: Make this recorder script:
#!/bin/bash LOGFILE="/path/to/log/file" SEMAPHORE="/path/to/log/file.semaphore" while : ; do read line while [[ -f $SEMAPHORE ]]; do sleep 1s done printf "%s\n" "$line" >> $LOGFILE done
Step 2: put the recorder into work:
Make a named pipe:
mkfifo $PIPENAME
Redirect your application's STDOUT & STDERR to the named pipe:
...things... &> $PIPENAME
Start the recorder:
/path/to/recorder.sh < $PIPENAME &
You might want to nohup
the above to make it survive logouts.
Done!
Step 3: If you need to logrotate, pause the recorder:
touch /path/to/log/file.semaphore mv /path/to/log/file /path/to/archive/of/log/file rm /path/to/log/file.semaphore
I suggest putting the above steps into its own script. Feel free to change the 2nd line to whatever log-rotating method you want to use.
Note : If you're handy with C programming, you might want to make a short C program to perform the function of recorder.sh
. Compiled C programs will certainly be lighter than a nohup-ed detached bash script.
Note 2: David Newcomb provided a helpful warning in the comments: While the recorder is not running then writes to the pipe will block and may cause the program to fail unpredictably. Make sure the recorder is down (or rotating) for as short time as possible.
So, if you can ensure that rotating happens really quickly, you can replace sleep
(a built-in command which accepts only integer values) with /bin/sleep
(a program that accepts float values) and set the sleep period to 0.5
or shorter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With