#!/bin/bash
# Skrypt rotatelogs cyklicznie zmienia pliki w katalogu /var/log w celu ich archiwizacji
# i zapobiega ich nadmiernemu powiększaniu. Skrypt wykorzystuje plik konfiguracyjny
# umożliwiający dostosowanie częstotliwości cyklicznych zmian każdego pliku dziennika.
# Wpisy w pliku konfiguracyjnym mają format nazwa_pliku_dziennika=okres_czasu, gdzie
# okres_czasu jest wyrażony w dniach. Jeżeli w pliku konfiguracyjnym
# nie ma wpisu dla określonego pliku dziennika, plik taki nie jest zmieniany
# cyklicznie częściej niż co siedem dni. Jeżeli okres_czasu ma wartość
# zero, skrypt nie zmienia cyklicznie danego pliku dziennika.

logdir="/var/log"      # Katalog z plikami dzienników może być inny.
config="$logdir/rotatelogs.conf"
mv="/bin/mv"
default_duration=7     # Domyślny 7-dniowy okres cyklicznych zmian.
count=0

duration=$default_duration

if [ ! -f $config ] ; then
  # Brak pliku konfiguracyjnego? Koniec. Możesz bezpiecznie usunąć
  # to polecenie warunkowe i nie dostosowywać działania skryptu
  # jeżeli pliku konfiguracyjnego nie ma.
  echo "$0: brak pliku konfiguracyjnego. Koniec działania." >&2; exit 1
fi

if [ ! -w $logdir -o ! -x $logdir ] ; then
  # Parametr -w oznacza uprawnienia do zapisu, a -x do uruchamiania pliku.
  # Oba uprawnienia są niezbędne do utworzenia pliku w systemie Unix lub
  # Linux. W przypadku ich braku wystąpi błąd.
  echo "$0: nie masz wystarczających uprawnień do katalogu $logdir." >&2
  exit 1
fi

cd $logdir

# Choć w poleceniu find można użyć standardowej notacji, np. ':digit:'
# jednak w wielu wersjach polecenie to nie obsługuje identyfikatorów
# POSIX, dlatego zastosowana jest notacja [0-9].
# Poniżej użyte jest bardzo skomplikowane polecenie find, wyjaśnione
# w dalszej części rozdziału. Przeczytaj, jeżeli Cię to interesuje!

for name in $(find . -maxdepth 1 -type f -size +0c ! -name '*[0-9]*' \
     ! -name '\.*' ! -name '*conf' -print | sed 's/^\.\///')
do
  count=$(( $count + 1 ))

  # Odczytanie wpisu z pliku konfiguracyjnego w celu wyszukania odpowiedniego
  # pliku dziennika.

  duration="$(grep "^${name}=" $config|cut -d= -f2)"   

  if [ -z "$duration" ] ; then 
    duration=$default_duration   # Jeżeli nie ma wpisu, stosowana jest domyślna wartość.
  elif [ "$duration" = "0" ] ; then
    echo "Okres cyklicznych zmian jest równy 0, plik $name pominięty."
    continue
  fi

  # Określenie nazw zmienianych cyklicznie plików. Prosta operacja.

  back1="${name}.1"; back2="${name}.2";
  back3="${name}.3"; back4="${name}.4";

  # Jeżeli najnowszy plik dziennika (nazwa w zmiennej back1) został zmodyfikowany
  # w zadanym okresie czasu, nie trzeba go zmieniać. Można to sprawdzić
  # za pomocą polecenia find -mtime.

  if [ -f "$back1" ] ; then
    if [ -z "$(find \"$back1\" -mtime +$duration -print 2>/dev/null)" ] 
    then
      echo -n "Od czasu utworzenia kopii pliku $name nie minęło $duration "
      echo "dni. Plik pominięty." ;   continue
    fi
  fi

  echo "Cykliczna zmiana pliku $name (co $duration dni)."

  # Cykliczna zmiana plików, począwszy od najstarszego. Należy jednak
  # zachować ostrożność, jeżeli któregoś z plików nie ma.

  if [ -f "$back3" ] ; then
    echo "... $back3 -> $back4" ; $mv -f "$back3" "$back4"
  fi
  if [ -f "$back2" ] ; then
    echo "... $back2 -> $back3" ; $mv -f "$back2" "$back3"
  fi
  if [ -f "$back1" ] ; then
    echo "... $back1 -> $back2" ; $mv -f "$back1" "$back2"
  fi
  if [ -f "$name" ] ; then
    echo "... $name -> $back1" ; $mv -f "$name" "$back1"
  fi
  touch "$name"
  chmod 0600 "$name"    # Ostatni krok: nadanie plikowi atrybutów rw-------.
done

if [ $count -eq 0 ] ; then
  echo -n "Żaden plik dziennika nie jest odpowiednio duży ani stary, "
  echo "aby go cyklicznie zmienić."
fi

exit 0
