Objective
So I have written a script that logs and rotates logs if it reaches certain size. I wish to capture all the errors and output by other commands also instead of the ones that I deliberately echo into the log.
The way I have achieved this is by redirecting STDIN and STDOUT to tee in a process substitution and have written a small function that makes use of savelog to rotate logs.
#!/bin/bash
LOGFILE="/var/log/ps.log"
exec > >(tee "$LOGFILE") 2>&1
LOGPATH="/var/log"
MAX_LOGFILE_SIZE=5
rotateLog() {
currentsize=$(du -k $LOGFILE | cut -f1)
if [ $currentsize -ge $MAX_LOGFILE_SIZE ]; then
savelog -dn $LOGFILE &>/dev/null
fi
}
while :; do
echo "A computer program can easily produce gibberish - especially if it has been provided with garbage beforehand. This program does something a little different. It takes a block of text as input and works out the proportion of characters within the text according to a chosen order. For example, an order of 2 means the program looks at pairs of letters, an order of 3 means triplets of letters and so on. The software can regurgitate random text that is controlled by the proportion of characters. The results can be quite surprising."
rotateLog
sleep 5
done
Problem
The problem is that even after the log ps.log gets rotated to ps.log.20180829131658, all the logs are still written to ps.log.20180829131658 and following error is thrown:
du: cannot access '/var/log/ps.log': No such file or directory ./ps.sh: line 12: [: -ge: unary operator expected
Leading to no further rotation of logs!!!
Assumption
I was assuming that once ps.log gets rotated to ps.log.20180829131658, a new log file ps.log will get created. But that definitely isn't the case since exec is executed only once (Can anyone please explain what exactly happens here?) i.e., at the beginning of the script.
Observation
What also I have observed that a new file descriptor is created for >(tee "$LOGFILE") that points to /var/log/p.log which gets reassigned to p.log.20180829131658! This is what clearly resulting in logs still being written to p.log.20180829131658. Can anyone please explain this behaviour?
root@b537ccc2c1ab:/var/log# ls -lrt
-rw-r--r-- 1 root root 7248 Aug 29 13:16 ps.log
root@b537ccc2c1ab:/var/log# ls -lrt /proc/*/fd
/proc/8979/fd:
total 0
l-wx------ 1 root root 64 Aug 29 13:16 3 -> /var/log/ps.log
lrwx------ 1 root root 64 Aug 29 13:16 2 -> /dev/pts/17
lrwx------ 1 root root 64 Aug 29 13:16 1 -> /dev/pts/17
lr-x------ 1 root root 64 Aug 29 13:16 0 -> pipe:[3889791]
root@b537ccc2c1ab:/var/log# ls -lrt
-rw-r--r-- 1 root root 11098 Aug 29 13:17 ps.log.20180829131658
root@b537ccc2c1ab:/var/log# ls -lrt /proc/*/fd
/proc/8979/fd:
total 0
l-wx------ 1 root root 64 Aug 29 13:16 3 -> /var/log/ps.log.20180829131658
lrwx------ 1 root root 64 Aug 29 13:16 2 -> /dev/pts/17
lrwx------ 1 root root 64 Aug 29 13:16 1 -> /dev/pts/17
lr-x------ 1 root root 64 Aug 29 13:16 0 -> pipe:[3889791]
How can achieve my objective with this logging and log rotation scheme? In particular how can my script write to newer log files besides log rotation while capturing errors and outputs of all other commands in my script alongside?
logrotateor some similar already existing software?logrotatewithcopytruncate. Thanks for your suggestion! But I would still prefer not to uselogrotatefor the aforementioned reason!logrotate. 2) Write your ownlogrotate. If it was me, I would go with the first option as installing a tried and tested piece of software is quicker and safer than writing my own. Also, in both cases, you are in effect installing a new piece of software. The only difference is who wrote it and how well and safely it's expected to perform. As a manager, I would also go with the first option, as I wouldn't want to waste my team's time and resources on developing a solution for something that there is already a (free!) solution available for.