So here’s the deal: you have an application running on a Linux box which generates log files. And these files keep mounting up and grow and grow and grow in both number and size and you have start considering cleaning up old logs which you don’t use anymore. I know about logrotate, it’s an awesome tool — assuming that:
- your application knows to close the current log file on a signal (e.g.
SIGHUP
) — sologrotate
can “rotate” it - or your application is ok with being “hung” for the period of time it takes
logrotate
to take a snapshot of the file and then truncate the existing one - and also your application doesn’t have an in-built log rotation mechanism itself
Now, if you happen to have a server application running which is doing a lot of extensive work, you know damn well that you cannot afford to freeze that even if it is for milliseconds, as that would deteriorate the experience to the clients “consuming” your server app. And if it so happens that the amount of logging you do is in the order of a few hundred Mb a day, then you know as well that this won’t take just a couple of milliseconds. Also, if you use something like Java — which is my case and what triggered in the end this blog post, unlikely you’ll be able to hook into SIGHUP
or similar; even more, if you already use one of the Log4J’s built-in mechanisms to auto-rotate the log files (be it on size, date etc), then again, you cannot use logrotate
unfortunately. However, you will still have each day a new log file being rotated (if you decided to have Log4J rotate on a daily basis) and these files keep mounting up and taking disk space; while you might keep an eye on the log files from the last week, unlikely I’d say in most cases you’d do the same with log files created 3 months ago — so there’s a lot of wasted disk space there!
And this is where this little script comes in — which is just a glorified call to the find
command — but wrapped up in a bash script which allows some easy and quick parameterization (is that even a word????). The way it works is very simple: you feed it a path/folder and a number of days and it deletes all the files in the given directory older than the number of days passed in. Ultimately it does something like this:
find /path/to/dir/* -mtime +N_DAYS -exec rm {} \; |
Where /path/to/dir
is the directory path and N_DAYS
is the number of days worth of files to keep — anything older than this will be deleted. On top of that it does a simple check as well that the path specified is a directory. Just plug this into your crontab and rather than remember the above syntax (simple to be fair), just use it in a command like this:
cleanup_old_logs.sh /var/logs/myapp 7 |
to delete anything in /var/logs/myapp/
older than a week (7 days). Here’s the source for it :
#!/bin/bash # Usage: cleanup_old_logs <folder> <days> # Removes all log files in the directory older than a certain number of days FOLDER=$1 N_DAYS=$2 # Validate if [ "$FOLDER" == "" ] || [ "$N_DAYS" == "" ] then echo "Usage: $0 folder number_of_days" exit 1 fi if [ ! -d "$FOLDER" ] then echo "$FOLDER is not a directory" exit 2 fi # Remove echo "Deleting files in $FOLDER older than $N_DAYS days" find $FOLDER/* -mtime +$N_DAYS -exec rm {} \; |
Or you can download it directly if copy-and-paste is not your thing: cleanup_old_logs.sh.gz
Thank you.
Exactly what I needed – and so concise. Thanks!
Just one problem; well not really a problem, just a redundancy – because the find command iterates through the files in the directory, there is no need for the wildcard as in “find $FOLDER/* -mtime +$N_DAYS -exec rm {} \;”.
“find $FOLDER -mtime +$N_DAYS -exec rm {} \;” would work just as well.
Thanks for the wonderful script, well could you please help how to control and delete only specific files types like log, syslog, xml etc… and if it is possible to create the log file for saving all the details of deleted files in it.
Thanks
Sud