Przejdź do treści
Lekcja 29 z 117

Kurs › Moduł 2 › Lekcja 29

Logi

⏱ ok. 11 min czytania· moduł 2: Procesy i jak działa system

Po tej lekcji: kursant znajduje w dzienniku to, czego szuka: błędy jednej usługi, z danego czasu, z poprzedniego startu; włącza trwały dziennik, pisze do logów ze skryptu i pilnuje, żeby logi nie zjadły dysku.

Wstęp

Jest dziesiąta rano. Awaria była w nocy, wszystko już działa, serwer w międzyczasie się zrestartował. Nie ma czego oglądać w top. Jedynym świadkiem jest dziennik.

Dziennik serwera to czarna skrzynka samolotu. Zapisuje wszystko, nikt go nie czyta, dopóki coś się nie rozłoży. A wtedy jest najważniejszą rzeczą na świecie. Dziś nauczymy się ją czytać: pytać o konkretną usługę, konkretną godzinę i konkretny start systemu. I sprawimy, żeby czarna skrzynka nie wyparowała przy restarcie.

Dwa systemy logów naraz

W Linuksie są dziś dwie księgowe i obie zapisują to samo.

systemd-journald to nowa księgowa z komputerem. Zbiera wszystko: komunikaty jądra, usług, wszystko, co usługi wypisują na ekran. Trzyma to w binarnej bazie z indeksami, więc szybko odpowiada na pytania typu „błędy usługi X od wczoraj”. Czyta się ją komendą journalctl. Zwykłym cat nie przeczytasz, to nie tekst.

rsyslog to stara księgowa z segregatorami. Dostaje kopię wpisów i rozkłada je do zwykłych plików tekstowych w /var/log. Te czyta się less, tail i grep, które już znasz.

I tu dystrybucje różnią się nazwami segregatorów:

Co
ogólny dziennik systemu/var/log/syslog/var/log/messages
logowania, sudo, SSH/var/log/auth.log/var/log/secure
jądro/var/log/kern.logw /var/log/messages
cronw /var/log/syslog/var/log/cron

Zapamiętaj parę auth.log i secure. Pierwsze pytanie przy podejrzeniu włamania brzmi: kto się logował? I od razu wiesz, gdzie szukać.

journalctl: pytania do księgowej

Samo journalctl wysypie wszystko od początku czasu, w less. Dlatego zawsze zadajesz pytanie. Najczęstsze:

journalctl -u zegarek -n 3
Nov 03 21:19:59 serwer zegarek.sh[221]: Dostepna pamiec: 6954 MB
Nov 03 21:20:01 serwer zegarek.sh[221]: Dostepna pamiec: 6954 MB

-u to usługa, -n 3 to ostatnie trzy wpisy. Na żywo, jak tail -f:

journalctl -f
journalctl -u nginx -f

W drugim oknie wpisuję logger -t kurs "na zywo" i od razu w pierwszym widzę:

Nov 03 21:20:30 serwer kurs[863]: na zywo

Czas:

journalctl --since "2026-11-02 02:00" --until "2026-11-02 02:15"
journalctl --since "1 hour ago"
journalctl --since yesterday -u ssh

To jest właśnie odpowiedź na hak: wszystko z kwadransa awarii, w jednym poleceniu.

Ważność. Każdy wpis ma priorytet od 0, „wszystko płonie”, do 7, „szczegóły dla programisty”. Po kolei: emerg, alert, crit, err, warning, notice, info, debug.

journalctl -p err -b
Nov 03 21:16:32 serwer (garek.sh)[152]: zegarek.service: Failed to set up mount namespacing: Operation not supported
Nov 03 21:17:15 serwer (psuty.sh)[275]: zepsuty.service: Failed to execute /usr/local/bin/zepsuty.sh: Exec format error
Nov 03 21:20:09 serwer kopia[785]: Brak miejsca na dysku /backup

-p err pokazuje błędy i wszystko gorsze. -b ogranicza do bieżącego startu systemu. To moje ulubione pierwsze polecenie po zalogowaniu na nieznany serwer: „co się tu sypie od ostatniego restartu”. Jak widzisz, u mnie same ślady po eksperymentach z poprzedniej lekcji. Dziennik pamięta.

Poprzedni start to -b -1, przedostatni -b -2. Listę startów pokaże journalctl --list-boots. Komunikaty samego jądra to journalctl -k.

I jeszcze uprawnienia. Zwykły użytkownik w journalctl widzi tylko swoje wpisy. Cały dziennik czytają root i członkowie grup systemd-journal, adm i wheel. Pustawy dziennik bez sudo to nie awaria, to brak klucza do pokoju.

Trwały dziennik: czarna skrzynka, która przetrwa

Journald może trzymać dziennik w dwóch miejscach. W pamięci, w /run/log/journal, i wtedy po restarcie jest czysto, jakby nic się nie stało. Albo na dysku, w /var/log/journal, i wtedy -b -1 ma sens. Domyślne ustawienie to Storage=auto, które działa sprytnie: jeśli folder /var/log/journal istnieje, zapisuje na dysk. Jeśli nie, tylko w pamięci.

Sprawdź u siebie:

ls -ld /var/log/journal
journalctl --list-boots

Jest folder i kilka startów na liście? Masz trwały dziennik. Nie ma folderu? Każdy restart kasuje czarną skrzynkę. Włączenie, w obu rodzinach tak samo:

sudo mkdir -p /etc/systemd/journald.conf.d
printf '[Journal]\nStorage=persistent\n' | sudo tee /etc/systemd/journald.conf.d/trwaly.conf
sudo systemctl restart systemd-journald

Storage=persistent sam założy /var/log/journal. Prostsza wersja, którą znajdziesz w wielu poradnikach, to samo sudo mkdir -p /var/log/journal i restart journald, bo przy auto folder wystarczy. Ja wolę jawne ustawienie: za rok ktoś przeczyta plik i będzie wiedział, że to celowe. To typowe zadanie na egzaminie RHCSA, więc przećwicz je na maszynie wirtualnej z RHEL.

A żeby dziennik nie zjadł dysku:

journalctl --disk-usage
sudo journalctl --vacuum-size=200M
sudo journalctl --vacuum-time=2weeks
Archived and active journals take up 8.0M in the file system.

Na stałe limit ustawiasz w tym samym pliku: SystemMaxUse=500M.

logger: wpis ze skryptu

Twoje skrypty też powinny pisać do dziennika, a nie do własnych plików porozrzucanych po dysku. Do tego jest logger:

logger "Test z kursu: pierwszy wpis"
logger -t kopia -p user.err "Brak miejsca na dysku /backup"
journalctl -t kopia
Nov 03 21:20:09 serwer kopia[785]: Brak miejsca na dysku /backup

-t to etykieta, po której potem szukasz. -p to priorytet w formacie „skąd.jak ważne”. Ten sam wpis trafił też do starej księgowej:

tail -2 /var/log/syslog
2026-11-03T21:20:09.123706+00:00 serwer root: Test z kursu: pierwszy wpis
2026-11-03T21:20:09.126097+00:00 serwer kopia: Brak miejsca na dysku /backup

Na RHEL szukasz go w /var/log/messages. W lekcji o monitoringu logger będzie naszym głównym narzędziem do ostrzegania.

rsyslog: własny segregator

rsyslog rozkłada wpisy po plikach według reguł „skąd.jak_ważne gdzie”. Skąd, czyli facility, to na przykład auth, cron, kern, mail, a dla własnych programów osiem wolnych szuflad: local0 do local7. Ubuntu trzyma reguły w /etc/rsyslog.d/50-default.conf:

auth,authpriv.*			/var/log/auth.log
*.*;auth,authpriv.none		-/var/log/syslog
kern.*				-/var/log/kern.log
mail.*				-/var/log/mail.log

Pierwsza linijka: wszystko z logowania do auth.log. Druga: wszystko do syslog, oprócz logowania, bo hasła i nazwy użytkowników nie powinny być w ogólnym pliku. Na RHEL te reguły są w samym /etc/rsyslog.conf i kierują do messages i secure.

Dodajmy własną szufladę:

echo 'local3.*    /var/log/moja-aplikacja.log' | sudo tee /etc/rsyslog.d/30-moja-aplikacja.conf
sudo rsyslogd -N1
sudo systemctl restart rsyslog
logger -p local3.warning -t moja-app "Kolejka zamowien przekroczyla 100"
sudo cat /var/log/moja-aplikacja.log
rsyslogd: version 8.2312.0, config validation run (level 1), master config /etc/rsyslog.conf
rsyslogd: End of config validation run. Bye.
2026-11-03T21:20:40.326741+00:00 serwer moja-app: Kolejka zamowien przekroczyla 100

rsyslogd -N1 sprawdza składnię, zanim zrestartujesz. Ta sama zasada co systemd-analyze verify, apachectl configtest i sshd -t: najpierw sprawdź, potem restartuj.

logrotate: kto wynosi stare segregatory

Pliki logów rosną bez końca. Bez sprzątania po roku /var/log zajmie cały dysk, a pełny dysk to serwer, który przestaje działać w najdziwniejszy możliwy sposób. Sprząta logrotate: co jakiś czas zamienia plik.log na plik.log.1, starsze kompresuje, najstarsze wyrzuca i zakłada pusty plik. Jak archiwum w urzędzie: bieżący segregator na biurku, cztery poprzednie w szafie, starsze na makulaturę.

Główne ustawienia w /etc/logrotate.conf, a reguły dla poszczególnych programów w /etc/logrotate.d/. Napiszmy regułę dla naszej aplikacji, /etc/logrotate.d/kurs:

/var/log/kurs.log {
    daily
    rotate 7
    maxsize 1M
    compress
    delaycompress
    missingok
    notifempty
    create 0640 root adm
    su root adm
}
  • daily — obracaj codziennie, a maxsize 1M — wcześniej, jeśli plik przekroczy megabajt.
  • rotate 7 — trzymaj siedem starych kopii.
  • compress i delaycompress — kompresuj, ale najnowszą starą kopię zostaw rozpakowaną, bo program mógł jeszcze do niej coś dopisać.
  • missingok, notifempty — nie krzycz, gdy pliku nie ma, nie ruszaj pustego.
  • create — załóż nowy pusty plik z takimi prawami.
  • su root adm — o tym za chwilę w typowym błędzie.

Sprawdzenie na sucho i wymuszenie obrotu:

sudo logrotate -d /etc/logrotate.d/kurs
sudo logrotate -f /etc/logrotate.d/kurs
ls -l /var/log/kurs.log*
-rw-r----- 1 root adm       0 Nov  3 21:20 /var/log/kurs.log
-rw-r----- 1 root adm      13 Nov  3 21:20 /var/log/kurs.log.1
-rw-r--r-- 1 root root 923982 Nov  3 21:20 /var/log/kurs.log.2.gz

Pusty bieżący, wczorajszy rozpakowany, starszy spakowany. Kto to uruchamia codziennie? [Ubuntu] U mnie timer systemd, logrotate.timer, co widać w systemctl list-timers. Na starszych systemach i bez systemd robi to skrypt w /etc/cron.daily/logrotate. W obu przypadkach nic nie musisz włączać.

dmesg: pamiętnik jądra

Jądro ma własny, mały bufor komunikatów w pamięci: wykryte dyski, podłączony pendrive, błędy sprzętu, wizyty zabójcy pamięci.

sudo dmesg -T --level=err,warn | tail -3
[Tue Nov  3 16:29:59 2026] Memory cgroup out of memory: Killed process 11404 (python3) total-vm:138056kB, anon-rss:102016kB, file-rss:7752kB, shmem-rss:0kB, UID:0 pgtables:280kB oom_score_adj:0
[Tue Nov  3 16:38:15 2026] I/O error, dev loop0, sector 2048 op 0x0:(READ) flags 0x0 phys_seg 32 prio class 2

-T zamienia sekundy od startu na zwykły czas. Pierwsza linijka to nasz zabójca z lekcji dwudziestego szóstego. Druga to błąd odczytu z dysku. Na prawdziwym dysku taka linijka to sygnał, żeby sprawdzić kopie zapasowe, zanim będzie późno. dmesg -w śledzi na żywo: podłącz pendrive i patrz.

Jak to działa pod spodem

Każdy program, który chce coś zapisać do dziennika, ma trzy drogi. Może pisać na ekran, a jeśli jest usługą systemd, jego ekran jest podłączony do journald. Może użyć starej funkcji syslog(), która wysyła wiadomość do gniazda /dev/log, a na systemach z systemd to gniazdo trzyma journald. Albo, jak jądro, pisze do własnego bufora, który journald też czyta.

Journald zapisuje wszystko w binarnych plikach w /var/log/journal/ID_MASZYNY/, z indeksami po usłudze, czasie, priorytecie i starcie. Kopię każdego wpisu podaje rsyslogowi, a ten przez swoje reguły rozpisuje ją po plikach tekstowych. Dlatego ten sam logger widziałeś i w journalctl, i w /var/log/syslog.

logrotate jest najprostszy: to zwykły program, który raz dziennie się budzi, czyta reguły, sprawdza w /var/lib/logrotate/status, kiedy ostatnio obracał dany plik, i zmienia nazwy. Program, który pisze do loga, musi się o tym dowiedzieć, bo inaczej dalej pisze do starego pliku pod nową nazwą. Do tego służą postrotate i copytruncate w regułach.

Ściąga flag

KomendaFlagaCo robi
journalctl-u USŁUGAwpisy jednej usługi
journalctl-fna żywo
journalctl-n Nostatnie N wpisów
journalctl-b / -b -1bieżący / poprzedni start
journalctl--list-bootslista startów w dzienniku
journalctl-p errbłędy i gorsze (0 emerg … 7 debug)
journalctl--since / --untilod / do kiedy
journalctl-ktylko jądro
journalctl-t ETYKIETAwpisy z daną etykietą
journalctl-g WZORZECszuka w treści
journalctl-o json-prettywszystkie pola wpisu
journalctl--disk-usage / --vacuum-size=Xile zajmuje / przytnij do X
logger-t / -petykieta / priorytet (np. user.err, local3.info)
logrotate-d / -f / -vna sucho / wymuś / gadatliwie
rsyslogd-N1sprawdza składnię konfiguracji
dmesg-T / -w / --level=err,warnczas po ludzku / na żywo / tylko ważne

⚠ Typowy błąd

Napisałeś własną regułę logrotate, jeszcze bez linijki su, i testujesz:

sudo logrotate -f /etc/logrotate.d/kurs
error: skipping "/var/log/kurs.log" because parent directory has insecure permissions (It's world writable or writable by group which is not "root") Set "su" directive in config file to tell logrotate which user/group should be used for rotation.

Jak to „niebezpieczne uprawnienia”? Przecież to /var/log! Sprawdzamy:

ls -ld /var/log
drwxrwxr-x 5 root syslog 4096 Nov  3 21:20 /var/log

[Ubuntu] Do /var/log może pisać grupa syslog, bo tak potrzebuje rsyslog. logrotate działa jako root i jest podejrzliwy: jeśli ktoś inny niż root może podmieniać pliki w tym folderze, to obracanie ich z uprawnieniami roota może być furtką do ataku. Więc odmawia.

Czemu systemowe logi się obracają? Bo w głównym /etc/logrotate.conf Ubuntu ma linijkę su root adm, a kiedy logrotate rusza codziennie, czyta całą konfigurację i to ustawienie obowiązuje wszystkich. My uruchomiliśmy go tylko z naszym plikiem, więc głównego nie przeczytał. Jak pracownik, który dostał jedną kartkę z instrukcji, a regulamin firmy został w szufladzie.

Naprawa: dopisz su root adm do własnej reguły, tak jak wyżej. Albo testuj całą konfigurację: sudo logrotate -d /etc/logrotate.conf. Na RHEL sprawdź ls -ld /var/log: jeśli pisać może tam tylko root, tego błędu nie zobaczysz, ale su w regule i tak nie zaszkodzi.

✎ Zadanie

  1. Sprawdź, czy Twój dziennik jest trwały. Jeśli nie, włącz go, zrestartuj maszynę i pokaż błędy z poprzedniego startu: journalctl -b -1 -p err.
  2. Przez logger zapisz wpis z etykietą zadanie29 i priorytetem warning. Znajdź go w journalctl po etykiecie i w pliku tekstowym: [Ubuntu] /var/log/syslog, [RHEL] /var/log/messages.
  3. Napisz regułę logrotate dla /var/log/moja-aplikacja.log: obrót co tydzień, pięć kopii, kompresja. Sprawdź ją na sucho.
Pokaż rozwiązanie

Trwały dziennik:

ls -ld /var/log/journal
journalctl --list-boots

Jeśli folderu nie było, włączyłeś go plikiem w /etc/systemd/journald.conf.d/ ze Storage=persistent i restartem systemd-journald. Po restarcie maszyny lista startów ma co najmniej dwie pozycje, a journalctl -b -1 -p err pokazuje błędy z poprzedniego życia serwera. Wpis z etykietą:

logger -t zadanie29 -p user.warning "Sprawdzam dziennik"
journalctl -t zadanie29
grep zadanie29 /var/log/syslog
Nov 03 21:20:46 serwer zadanie29[902]: Sprawdzam dziennik
2026-11-03T21:20:46.852886+00:00 serwer zadanie29: Sprawdzam dziennik

Na RHEL zamiast /var/log/syslog grep idzie do /var/log/messages. I reguła logrotate, /etc/logrotate.d/moja-aplikacja:

/var/log/moja-aplikacja.log {
    weekly
    rotate 5
    compress
    missingok
    notifempty
    su root adm
}
sudo logrotate -d /etc/logrotate.d/moja-aplikacja
rotating pattern: /var/log/moja-aplikacja.log  weekly (5 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/moja-aplikacja.log
  log does not need rotating (log has already been rotated)

Dobrze, że testowałeś na sucho. „Nie trzeba obracać” to też odpowiedź, i to taka, która niczego nie zepsuła. Na RHEL linijka su może być zbędna, ale nie szkodzi.

Co dalej

W logach jądra przewijały się dyski, urządzenia i sterowniki. W następnej lekcji zaglądamy do maszynowni: jaki mamy procesor, pamięć, dyski i karty, jak jądro ładuje sterowniki, jak zmienić jego ustawienia w locie i kim jest udev, który nadaje nazwy podłączanym urządzeniom.