Skrypt do wydzielania logów

Archiwalne, stare wpisy FAQ i HowTo Użytkowników
Awatar użytkownika
turox
Posty: 49
Rejestracja: 19 września 2010, 15:40
Lokalizacja: Tychy

Skrypt do wydzielania logów

Post autor: turox »

Skrypt do wydzielania logów np. postfiksa.

W odróżnieniu od większości nowych użytkowników forum nie mam akurat żadnego problemu, zamiast tego na dzień dobry chciałem się podzielić prostym skryptem, który napisałem jakiś czas temu - bo podobnego narzędzia nie znalazłem, a było mi potrzebne. Może komuś też się przyda.

Do czego służy?

Czasami zdarza się sytuacja, że musimy przeszukać jakiś plik logów i często ma on spory rozmiar. Jeśli mamy np. 200MB plik i chcemy go przeszukać narzędziem grep bo ktoś do nas przyszedł i szuka śladów maila sprzed ośmiu dni, to trzeba przejrzeć cały plik. Pół biedy jak wiemy czego szukamy, ale jak szukamy wiele razy, a wiemy np. że mail ma być gdzieś pomiędzy zeszłym poniedziałkiem a zeszłą środą, to nie ma przecież sensu szukać w całym 200-megowym pliku. Przydałoby się jakieś narzędzie do wydzielenia z tego dużego pliku logów mniejszego pliku, na którym będziemy szukać oszczędzając czas. Można zrobić to z pocą polecenia tail, ale skąd wiedzieć ile linii trzeba wyciągnąć? Można metodą Macajewa, ale można też moim małym narzędziem. Co to robi dwie rzeczy:
  1. Tworzy indeks zdefiniowanego pliku logów, w którym mamy kolejne daty i numery linii, od których się zaczynają wpisy.
  2. Wydziela z pliku logów tylko te dni, które chcemy i zapisuje do pliku o nazwie ,,logwork''. Ten plik jest zawsze mniejszy, i szybciej się w nim szuka.
Skrypt jest testowany na logach postfiksa ale powinien działać z większością logów tekstowych, ważne jedynie żeby pierwsze sześć znaków oznaczało datę:

Kod: Zaznacz cały

Aug 30 ....
Aug 31 ....
Sep 1 ....
Sep 2 ....
Format polecenia uruchomienia skryptu jest prosty:

Kod: Zaznacz cały

wydziel.sh [ile_dni_wstecz] [ile_dodatkowo_w_przod]
Jeśli nie podamy drugiego parametru, system wydzieli logi do dnia bieżącego. Jeśli nie podamy żadnego, system wydzieli TYLKO dzisiejsze informacje.

Przykładowo - mamy dzisiaj 20 września i chcemy wydzielić dzisiejsze wpisy.
  • Wpisuję polecenie w terminalu:

    Kod: Zaznacz cały

    wydziel.sh

    Kod: Zaznacz cały

    Sprawdzam indeks
    Brak indeksu
    Robię nowy indeks pliku /var/log/mail/info
    Wydzielam logi od dnia Sep 20 do dnia Sep 20
    Gotowe, wydzielone logi w pliku logwork
  • Jeśli chcę wydzielić logi od 15 września do dzisiaj: 20 minus 15 to pięć, zatem:

    Kod: Zaznacz cały

    wydziel.sh 5

    Kod: Zaznacz cały

    Wydzielam logi od dnia Sep 15 do dnia Sep 20
    Gotowe, wydzielone logi w pliku logwork
  • Jeśli chcemy wydzielić logi do 14 września do 15 września:

    Kod: Zaznacz cały

    wydziel.sh 6 1

    Kod: Zaznacz cały

    Wydzielam logi od dnia Sep 14 do dnia Sep 15
    Gotowe, wydzielone logi w pliku logwork
  • Jeśli chcemy wydzielić logi jedynie z 14 września:

    Kod: Zaznacz cały

    wydziel.sh 6 0

    Kod: Zaznacz cały

    Wydzielam logi od dnia Sep 14 do dnia Sep 14
    Gotowe, wydzielone logi w pliku logwork
Na przeciętnym komputerze wszystko, z wyjątkiem generowania indeksu trwa poniżej jednej sekundy. Indeks generuje się tyle ile trzeba przelecieć grepem cały plik, jednak robi się to raz dziennie. Skrypt sam sprawdza czy ma indeks i czy jest on aktualny - i jeśli nie, to go tworzy od nowa.

Skrypt:

Kod: Zaznacz cały

#!/bin/bash

###################################################
#
# Wydzielanie logów według daty (c) Zbigniew Cofała
#
###################################################

LOGFILE="/var/log/mail/info"
NDXFILE="$LOGFILE.ndx"
LOGWORK="/var/log/mail/logwork"

robindex()
{
   echo "Robię nowy indeks pliku $LOGFILE"
   cut -c-6 $LOGFILE | uniq |while read ln ; do
      linia=`grep ^"$ln" -n $LOGFILE |head -n1 |cut -d: -f1`
      echo -ne "$ln:$linia\n"
   done | sort -t: -k2 -n > $NDXFILE
}

wydziel()
{
   dniwstecz="$1"
   iledni="$2"

   dniwsteczplus=`expr $dniwstecz - $iledni - 1`
   dniwsteczczyt=`expr $dniwstecz - $iledni`

   odkiedy=`LC_TIME=POSIX date '+%b %e' --date="$dniwstecz days ago"`
   dokiedy=`LC_TIME=POSIX date '+%b %e' --date="$dniwsteczplus days ago"`
   dokiedyczyt=`LC_TIME=POSIX date '+%b %e' --date="$dniwsteczczyt days ago"`


   aktual=`grep ^"$odkiedy" $NDXFILE |cut -d: -f2`
   aktualdo=`grep ^"$dokiedy" $NDXFILE |cut -d: -f2`
   linesum=`wc -l < $LOGFILE`
   if [ -z $aktual ]; then aktual=0; fi
   let iletail=$linesum-$aktual+1
   let ilelinii=$aktualdo-$aktual

   echo "Wydzielam logi od dnia $odkiedy do dnia $dokiedyczyt";

   if [ -n "$aktualdo" ]; then
      tail -n $iletail $LOGFILE | head -n $ilelinii > $LOGWORK
   else
      tail -n $iletail $LOGFILE > $LOGWORK
   fi
   echo "Gotowe, wydzielone logi w pliku `basename $LOGWORK`"
}

sprawdzindex()
{
   if [ ! -r $NDXFILE ]; then
      echo "Brak indeksu"
      robindex
   else
      lastday=`tail -n1 $NDXFILE |cut -d: -f1`
      dzisiaj=`LC_TIME=POSIX date '+%b %e'`
      if [ "$lastday" != "$dzisiaj" ]; then
         echo "Indeks jest stary"
         robindex
      else
         echo "Indeks jest aktualny"
      fi
   fi
}

if [ $# -eq 0 ] ; then
   dniwstecz="0"
   iledni="0"
else
   dniwstecz="$1"
   iledni="$2"
   if [ -z "$2" ]; then iledni="$dniwstecz" ; fi
   if ([ "$iledni" -gt "$dniwstecz" ] || [ "$iledni" -lt 0 ]); then let iledni="$dniwstecz"; fi
fi

echo "Sprawdzam indeks"
sprawdzindex
wydziel $dniwstecz $iledni
Pozdrawiam, mam nadzieję, że komuś się przyda. Jeśli ktoś ma jakieś uwagi, to bardzo proszę.
Zablokowany