#!/bin/bash

# Starting with the oldest, delete enough compressed log files (if they exist)
# until /var/log occupies less than
BUDGET_MB=500 # MiBytes

# A hook so we can override the number above without having to edit this file.
# (The extra config file is also used by the rotate_logs_by_size script.)
[ -r /etc/sysconfig/logrotate ] && . /etc/sysconfig/logrotate

verbose=0
[ "$1" = -v ] && verbose=1

while : ; do
  set -- $(du -sk /var/log 2>/dev/null)
  used_k=$1
  budget_kb=$((BUDGET_MB * 1024))

  # How much do we need to delete?
  excess_k=$((used_k - budget_kb))

  [ $excess_k -le 0 ] && break # All is well: nothing to do.

  # We have an excess, so we must look for old files to delete.
  # The while-loop's condition means that we loop until either we have deleted
  # the excess or we run out of eligible files, whichever happens first.
  find /var/log /var/log/openvswitch /var/log/blktap /var/log/xen \
    -maxdepth 1 -name '*.gz' -printf '%T@ %k %p\n' | \
    sort -g -k1 | \
    while [ $excess_k -gt 0 ] && read modtime filesize filename; do
      logmsg="Removing ${filename} (${filesize}kB) as logs are ${excess_k}kB over budget ${budget_kb}kB"
      logger -t logrotate "${logmsg}"
      [ $verbose -eq 1 ] && echo "${logmsg}"
      rm -f "${filename}"
      let excess_k-=$filesize
      # The next line does nothing, but its exit status will be returned by the
      # while statement when we exit the loop. This indicates which of the
      # while-loop's two conditions was broken to end the loop.
      [ $excess_k -gt 0 ] # exit-code 0 ("success") iff an excess remains.
    done && break
  # The line above breaks out of outer loop if inner loop returned exit code 0.
  # The return value from the while...do...done above is the return value of the
  # last statement inside its loop, or success if the loop contents never ran
  # (i.e. if we found no files).  Therefore we break out of the outer loop here
  # only if we ran out of files to delete while still wanting to delete more: a
  # bad thing.

  # Otherwise, continue the outer loop in case new logging pushed us over the
  # limit again while we were busy deleting.
done
