Creating A Rotating Logger In Bash

Recently I was working on writing some bash script to gather some data. The data of course has to be written to somewhere, and just printing it to the console wasn’t an option because the script would run from time to time and it is the historical data (over a course of hours, or even days) that holds the real value.

Writing data to a file is easy, but if you leave it unattended the file will keep on growing. Just removing the file at a certain interval won’t work either because then you have a period where there is no historical data anymore. What I basically wanted were the features offered by all logger libraries, being a rotating logger that automatically overwrites files. I couldn’t immediately find any source that I could use so I decided to write my own.

The full script is shown below. You can easily specify the size of each file as well as how many files you want to store, the directory and the name of the file.

#!/bin/bash

directory="logs"
fileName="systemdata"
fileExtension=".log"
dateFormat="%F %H:%M"

# Size in bytes
maxSize=$((100 * 1024))
# Note: this indicates the amount of archive files to keep.
# It does not include the file we are currently writing to.
maxFiles=5

function logfile {
	name=$directory/$fileName
	if [ $1 ]; then
		name+=-$1
	fi
	name+=$fileExtension

	echo $name
}


mkdir -p $directory
if [ ! -f $(logfile) ]; then
	touch $(logfile)
fi

fileSize=$(stat --printf="%s" $(logfile))
if [ $fileSize -gt $maxSize ]; then
	for ((index=$(($maxFiles - 1)); index>=0; --index)); do
		file=$(logfile $index)
		if [ -f $file ]; then
			mv $(logfile $index) $(logfile $(($index + 1)))
		fi
	done

	rm -f $(logfile $maxFiles)
	mv $(logfile) $(logfile 0)
	touch $(logfile)
fi


echo -n "== BEGIN == " >> $(logfile)
date +"$dateFormat" >> $(logfile)

echo "-- top -- ">> $(logfile)
top -b -n 1 | grep -v '\[' >> $(logfile)

echo "-- df -- " >> $(logfile)
df >> $(logfile)

echo "-- du --" >> $(logfile)
du -h --max-depth=1 >> $(logfile)

echo -n "== END == " >> $(logfile)
date +"$dateFormat" >> $(logfile)
echo >> $(logfile)

The biggest flaw in the design is that it only will check if the current log file is too large at the beginning of the script. Ideally you would want to have a function to write a log file that will take care of printing the date, as well as checking whether a new file needs to be started.

I hope my work can be of use for others, either to be used as-is or as an inspiration. In either case leave me a comment.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.