devops2025-06-03·7·45/348

Automated Log Cleanup Script for /var/log on Linux

Shell script to automatically clean up old log files in /var/log, including compression, rotation, and size-based cleanup with logging.

Automated Log Cleanup Script for /var/log on Linux

Log files grow unbounded and can fill up your disk if not managed properly. I wrote a cleanup script after a production server hit 100% disk usage due to accumulated logs. This script handles rotation, compression, and size-based cleanup.

Environment

  • OS: Ubuntu 22.04 LTS
  • Problem: /var/log grew to 15GB, consuming 75% of root partition
  • Solution: Automated cleanup script with cron job
$ du -sh /var/log
15G     /var/log

$ df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       20G   18G   2G  90% /

The Problem

$ sudo du -sh /var/log/*
5.2G    /var/log/syslog
4.1G    /var/log/syslog.1
3.8G    /var/log/nginx
1.2G    /var/log/journal
800M    /var/log/apt

Multiple large log files accumulating without rotation.

Solution

Basic Cleanup Script

#!/bin/bash
# /usr/local/bin/log-cleanup.sh
# Automated log cleanup for /var/log

set -euo pipefail

LOG_DIR="/var/log"
LOG_RETENTION_DAYS=30
COMPRESSED_RETENTION_DAYS=90
MAX_LOG_SIZE_MB=100
LOGFILE="/var/log/log-cleanup.log"

log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOGFILE"
}

log_message "Starting log cleanup..."

# 1. Rotate large log files
find "$LOG_DIR" -type f -name "*.log" -size +${MAX_LOG_SIZE_MB}M -exec bash -c '
    for file do
        if [ -f "$file" ]; then
            timestamp=$(date +%Y%m%d_%H%M%S)
            gzip -9 "$file"
            mv "${file}.gz" "${file}.${timestamp}.gz"
            touch "$file"
            log_message "Rotated: $file"
        fi
    done
' _ {} +

# 2. Remove old uncompressed logs
find "$LOG_DIR" -type f -name "*.log" -mtime +${LOG_RETENTION_DAYS} -delete
log_message "Removed uncompressed logs older than ${LOG_RETENTION_DAYS} days"

# 3. Remove old compressed logs
find "$LOG_DIR" -type f \( -name "*.gz" -o -name "*.bz2" -o -name "*.xz" \) \
    -mtime +${COMPRESSED_RETENTION_DAYS} -delete
log_message "Removed compressed logs older than ${COMPRESSED_RETENTION_DAYS} days"

# 4. Clean journal logs
journalctl --vacuum-time=30d --vacuum-size=500M
log_message "Cleaned journal logs"

# 5. Clean apt cache
apt-get clean
log_message "Cleaned apt cache"

# 6. Clean tmp files
find /tmp -type f -atime +7 -delete 2>/dev/null || true
log_message "Cleaned /tmp"

# Report disk usage after cleanup
DISK_USAGE=$(df / --output=pcent | tail -1 | tr -d '% ')
log_message "Disk usage after cleanup: ${DISK_USAGE}%"
log_message "Log cleanup completed"

Advanced Cleanup Script with Email Alerts

#!/bin/bash
# /usr/local/bin/log-cleanup-advanced.sh

set -euo pipefail

LOG_RETENTION_DAYS=30
ALERT_THRESHOLD=80
ADMIN_EMAIL="admin@example.com"
HOSTNAME=$(hostname)

# Calculate total log size before cleanup
BEFORE_SIZE=$(du -sh /var/log 2>/dev/null | cut -f1)

# Run cleanup
/usr/local/bin/log-cleanup.sh

# Calculate size after
AFTER_SIZE=$(du -sh /var/log 2>/dev/null | cut -f1)
DISK_USAGE=$(df / --output=pcent | tail -1 | tr -d '% ')

# Send alert if disk usage is still high
if [ "$DISK_USAGE" -gt "$ALERT_THRESHOLD" ]; then
    echo "Disk usage on ${HOSTNAME} is ${DISK_USAGE}% after cleanup.
Before: ${BEFORE_SIZE}
After: ${AFTER_SIZE}" | mail -s "Disk Alert: ${HOSTNAME}" "$ADMIN_EMAIL"
fi

Make Scripts Executable and Schedule

# Make executable
$ sudo chmod +x /usr/local/bin/log-cleanup.sh
$ sudo chmod +x /usr/local/bin/log-cleanup-advanced.sh

# Schedule with cron
$ sudo crontab -e

# Add these lines:
# Run basic cleanup daily at 2 AM
0 2 * * * /usr/local/bin/log-cleanup.sh

# Run advanced cleanup weekly on Sunday
0 3 * * 0 /usr/local/bin/log-cleanup-advanced.sh

Configure logrotate

# Create custom logrotate config
$ sudo cat > /etc/logrotate.d/custom << 'EOF'
/var/log/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    size 100M
    create 0640 root adm
    sharedscripts
    postrotate
        /usr/lib/rsyslog/rsyslog-rotate 2>/dev/null || true
    endscript
}
EOF

# Test logrotate
$ sudo logrotate -d /etc/logrotate.d/custom

Verify Cleanup

# Check disk usage
$ df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       20G   8G   12G  40% /

# Check /var/log size
$ du -sh /var/log
3G      /var/log

# Verify cron job is scheduled
$ sudo crontab -l | grep log-cleanup
0 2 * * * /usr/local/bin/log-cleanup.sh

Lessons Learned

  1. Always test cleanup scripts on non-production systems first.
  2. Use set -euo pipefail to catch errors early.
  3. Monitor disk usage after implementing cleanup to verify it works.
  4. Keep compressed logs longer than uncompressed for debugging.
  5. Log cleanup activity to a separate file for auditing.

This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.