Logi
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.log | w /var/log/messages |
| cron | w /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 3Nov 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 -fW drugim oknie wpisuję logger -t kurs "na zywo" i od razu w pierwszym widzę:
Nov 03 21:20:30 serwer kurs[863]: na zywoCzas:
journalctl --since "2026-11-02 02:00" --until "2026-11-02 02:15"
journalctl --since "1 hour ago"
journalctl --since yesterday -u sshTo 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 -bNov 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-bootsJest 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-journaldStorage=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=2weeksArchived 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 kopiaNov 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/syslog2026-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 /backupNa 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.logPierwsza 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.logrsyslogd: 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 100rsyslogd -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.gzPusty 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
| Komenda | Flaga | Co robi |
|---|---|---|
| journalctl | -u USŁUGA | wpisy jednej usługi |
| journalctl | -f | na żywo |
| journalctl | -n N | ostatnie N wpisów |
| journalctl | -b / -b -1 | bieżący / poprzedni start |
| journalctl | --list-boots | lista startów w dzienniku |
| journalctl | -p err | błędy i gorsze (0 emerg … 7 debug) |
| journalctl | --since / --until | od / do kiedy |
| journalctl | -k | tylko jądro |
| journalctl | -t ETYKIETA | wpisy z daną etykietą |
| journalctl | -g WZORZEC | szuka w treści |
| journalctl | -o json-pretty | wszystkie pola wpisu |
| journalctl | --disk-usage / --vacuum-size=X | ile zajmuje / przytnij do X |
| logger | -t / -p | etykieta / priorytet (np. user.err, local3.info) |
| logrotate | -d / -f / -v | na sucho / wymuś / gadatliwie |
| rsyslogd | -N1 | sprawdza składnię konfiguracji |
| dmesg | -T / -w / --level=err,warn | czas 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/kurserror: 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/logdrwxrwxr-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
- 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. - Przez
loggerzapisz wpis z etykietązadanie29i priorytetemwarning. Znajdź go wjournalctlpo etykiecie i w pliku tekstowym: [Ubuntu]/var/log/syslog, [RHEL]/var/log/messages. - 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-bootsJeś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/syslogNov 03 21:20:46 serwer zadanie29[902]: Sprawdzam dziennik
2026-11-03T21:20:46.852886+00:00 serwer zadanie29: Sprawdzam dziennikNa 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-aplikacjarotating 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.