Jak ograniczyć rozmiar pliku dziennika za pomocą >>


24

Jak mogę ograniczyć rozmiar zapisanego pliku dziennika >>do 200 MB?

$ run_program >> myprogram.log

1
Czy chcesz zabić program po 200 MB? A może chcesz ostatnie 200 MB ze wszystkim starszym w segmencie bitów?
Aaron D. Marasco,

nie, proces nie może się zatrzymać, dopóki nie zostanie ręcznie zabity
David

Postanowiłem pójść na Logrotate, dziękuję wszystkim za cenne wkłady
David

Odpowiedzi:


9

Jeśli twoja aplikacja (tj. run_program) Nie obsługuje ograniczania rozmiaru pliku dziennika, możesz okresowo sprawdzać rozmiar pliku w pętli za pomocą zewnętrznej aplikacji lub skryptu.

Możesz także użyć logrotate(8)do obracania dzienników, ma sizeparametr, którego możesz użyć do swoich celów:

Dzięki temu plik dziennika jest obracany po osiągnięciu określonego rozmiaru. Rozmiar można określić w bajtach (domyślnie), kilobajtach (sizek) lub megabajtach (sizem).


1
+1 Pliki logów z powtarzającymi się informacjami często mogą zostać skompresowane w rzędach wielkości.
użytkownik nieznany

Czy logrotate obcina pliki, czy po prostu kopiuje je lub przenosi? Ponieważ zadziała to tylko wtedy, gdy plik powiązany z fd zostanie obcięty. Jeśli jest to plik mv'd, plik będzie się powiększał, jeśli zostanie odłączony, pozostanie otwarty i będzie się rozwijał aż do zakończenia procesu ... IIRC logrotuje kopie, odłącza i tworzy nowy plik, dlatego często trzeba wysyłać SIGHUP do dæmons, gdy ich dzienniki zostały obrócone.
Michael Trausch

Zauważ, że nawet jeśli jest on obcięty, istnieje problem, jeśli plik nie został otwarty w trybie dołączania (pliki dziennika powinny zawsze być otwierane w trybie dołączania, ale z mojego doświadczenia często tak nie jest)
Random832

Logrotate może się obracać, gdy plik osiągnie określony rozmiar, codziennie, co tydzień itp. Może również kompresować, a także możesz użyć postscriptopcji, aby konfiguracja logrotate została wysłana SIGHUPdo programu.
laebshade

12

Jeśli twój program nie musi zapisywać INNYCH plików, które byłyby większe niż ten limit, możesz poinformować jądro o tym limicie za pomocą ulimit. Przed uruchomieniem polecenia uruchom to, aby ustawić limit wielkości pliku 200 MB dla wszystkich procesów uruchomionych w bieżącej sesji powłoki:

ulimit -f $((200*1024))

To ochroni twój system, ale może być niebezpieczne dla programu zapisującego plik. Jak sugeruje eyazici , rozważ skonfigurowanie logrotateplików dziennika do przycinania, gdy osiągną określony rozmiar lub wiek. Możesz odrzucić stare dane lub zarchiwizować je na pewien czas w szeregu skompresowanych plików.


ogranicza to rozmiar każdego pliku zapisanego przez program
Kim

Prawdziwe. Jeśli program miał uzasadnioną potrzebę napisania innych dużych plików, potrzebne byłoby inne rozwiązanie.
Caleb

6

Możesz utworzyć nowy obraz systemu plików, zamontować go za pomocą urządzenia pętli i umieścić plik dziennika w tym systemie plików:

dd if=/dev/zero of=./200mb.img bs=1024 count=200000 # create new empty 200MB file
mkfs.ext2 200mb.img # or ext3, or whatever fits your needs
mkdir logs
sudo mount -t ext2 -o loop 200mb.img logs # only root can do '-o loop' by default
run_program >>logs/myprogram.log

Możesz również użyć tmpfszamiast pliku, jeśli masz wystarczającą ilość pamięci.


Kreatywny pomysł ... który pozostawia programowi, co zrobić, gdy się skończy.
Aaron D. Marasco,

6

Możesz obciąć dane wyjściowe za pomocą head:

size=$((200*1024*1024-$(stat -c %s myprogram.log)))
run_program | head -c ${size} >> myprogram.log

Bardzo kreatywne. Tylko uwaga, że ​​zadziałałoby to tylko w celu ograniczenia NOWYCH danych zapisywanych do pliku, nie wziąłby pod uwagę, jak duży lub mały był już plik.
Caleb

2
Należy pamiętać, że prawdopodobnie spowoduje to zabicie programu (za pomocą SIGPIPE) po osiągnięciu limitu rozmiaru, zamiast odrzucania danych.
Random832

1
Myślałem podobnie z pewną ddmagią, ale tak @ Random832 ma rację, dostaniesz SIGPIPEas head/ dd/ whateverupuszcza.
Aaron D. Marasco,

A co z ignorowaniem go za pomocą trap '' SIGPIPE?
smoking

Lub zamiast tego potokuj { head -c "$size" >> log; cat > /dev/null; }.
Stéphane Chazelas

5

W pakiecie apache2-utilsznajduje się narzędzie o nazwie rotatelogs, może być dla Ciebie pomocne.

Streszczenie:

rotatelogs [-l] [-L linkname ] [-p program ] [-f] [-t] [-v] [-e] [-c] [-n liczba plików ] czas rotacji pliku dziennika | rozmiar pliku (B | K | M | G) [ offset ]

Przykład:

your_program | rotatelogs -n 5 /var/log/logfile 1M

Pełny podręcznik można przeczytać pod tym linkiem .


Link nie istnieje.
Alexander Gonchiy,

1

Jestem pewien, że oryginalny plakat znalazł rozwiązanie. Oto kolejny dla innych, którzy mogą przeczytać ten wątek ...

Curtail ogranicza rozmiar danych wyjściowych programu i zachowuje ostatnie 200 MB danych wyjściowych za pomocą następującego polecenia:

$ run_program | curtail -s 200M myprogram.log

Referencje

UWAGA: Jestem opiekunem powyższego repozytorium. Po prostu udostępniam rozwiązanie ...


Podoba mi się pomysł ograniczenia. Nie znam się tak dobrze na C, więc czy jest szansa na dostarczenie pliku binarnego? lub przynajmniej szczegółowe instrukcje, jak to zainstalować?
Felipe

0

Ponieważ jest to tekst, napisałbym skrypt w twoim ulubionym języku i dopasowałem go do tego. Niech poradzi sobie z plikiem I / O (lub zachowa to wszystko w pamięci, a następnie zrzuci na SIGHUPlub podobne). W tym celu zamiast 200 MB pomyślałbym o „rozsądnej” liczbie wierszy do śledzenia.


Przechowywanie 200 MB danych dziennika w pamięci bez żadnego innego powodu niż możliwość obcięcia nie jest zbyt dobrym wykorzystaniem zasobów systemowych. Nie robi też liczenia linii na dużym pliku dziennika. Polecam korzystanie z narzędzi zbudowanych w tym celu, takich jak syslogi logrotate.
Caleb,

0

Poniższy skrypt powinien wykonać zadanie.

LOG_SIZE=500000
NUM_SEGM=2
while getopts "s:n:" opt; do
  case "$opt" in
    s)
      LOG_SIZE=$OPTARG
      ;;
    n)
      NUM_SEGM=$OPTARG
      ;;
  esac
done
shift $((OPTIND-1))
if [ $# == 0 -o -z "$1" ]; then
    echo "missing output file argument"
    exit 1
fi
OUT_FILE=$1
shift
NUM=1
while :; do
    dd bs=10 count=$(($LOG_SIZE/10)) >> $OUT_FILE 2>/dev/null
    SZ=`stat -c%s $OUT_FILE`
    if [ $SZ -eq 0 ]; then
        rm $OUT_FILE
        break
    fi
    echo -e "\nLog portion finished" >> $OUT_FILE
    mv $OUT_FILE $OUT_FILE.n$NUM
    NUM=$(($NUM + 1))
    [ $NUM -gt $NUM_SEGM ] && NUM=1
done

Ma kilka oczywistych skrótów, ale ogólnie robi to, o co prosiłeś. Podzielą dziennik na kawałki o ograniczonym rozmiarze, a ilość kawałków jest również ograniczona. Wszystkie można określić za pomocą argumentów wiersza polecenia. Plik dziennika jest również określany za pomocą wiersza polecenia.

Zwróć uwagę na małą gotcha, jeśli używasz jej z demonem, który rozwidla się w tle. Użycie potoku uniemożliwi przejście demona w tło. W tym przypadku istnieje składnia (prawdopodobnie specyficzna dla bash), aby uniknąć problemu:

my_daemon | ( logger.sh /var/log/my_log.log <&0 & )

Zwróć uwagę, że <&0choć pozornie zbędne, nie będzie działać bez tego.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.