Linux naplózás

 

Linux naplózás

A systemd egyik hasznos szolgáltatása, hogy egységesen kezeli az egyes folyamatok és a rendszer naplózását. Korábban az egyes folyamatok maguk kezelték a naplózásukat, így az egyes események részleteinek felderítése sokszor igen nehézkessé vált, mivel a problémák felderítéséhez több különböző helyen és különböző formátumú naplófájlt kellett átnézni. Mivel a rendszer egyes folyamatait a systemd indítja és kezeli, ezért logikus gondolat, hogy az ezek által küldött üzeneteket is a systemd kezelje. Éppen ez történik. Erre szolgál megoldásként az, hogy a systemd.journald naplózási szolgáltatása automatikusan gyűjti és tárolja egy központi helyen binárisan (és nem szövegesen) a rendszer eseményeit, a kernel üzeneteket, szolgáltatások indítását és leállítását, az általuk küldött hibákat, figyelmeztetéseket és más információkat. EZt a bináris adatbázist nevezzük Journal-nak. A bináris tárolási mód az egyes bejegyzések hatékonyabb feldolgozását teszi lehetővé. Ha például egyszerű szövegesen szeretnénk a naplóbejegyzéseket megjeleníteni, vagy egy grafikus program számára szeretnénk ezeket bemenő adatként átküldeni, a naplóbejegyzések bináris adatbázisából ezt hatékonyabban lehet megtenni.

A felhasználók a naplóbejegyzéseket egységesen a journalctl nevű parancssoros eszközzel tudják megtekinteni és kezelni.


A rendszeridő beállítása

A bináris tárolás egyik előnye, hogy a naplóbejegyzések időpontja helyi és UTC idő alapján is megtekinthető. (Alapértelmezetten a helyi idő alapján írja ki.)

Az UTC (Coordinated Universal Time) az időmérés egyetemesen koordinált világidejét jelenti, melyet a Nemzetközi Atomidőszámítási Intézet (International Bureau of Weights and Measures) koordinál. Az UTC egyenlő a Greenwichi középidővel (GMT). Használata azért nagyon fontos, mert a kommunikáció nem áll meg az egyes időzónák határain, és így szükség egy, az időzónáktól független egyetemes időszámítás. Ez az UTC, melyet az időbélyegeiben az UTC vagy a Z betű jelöl. (2023-06-17 09:30:00 UTC vagy 09:30:00Z) Az UTC-ben nem használjuk a téli és nyári időszámítást.

Az időzónák kezelésére a timedatectl parancs áll rendelkezésünkre. Az időzónákat a list-timezones paranccsal tudjuk kilistázni. A lista nagyon hosszú, így használjuk a grep parancsot, ha egy bizonyos időzónát keresünk:

timedatectl list-timezones
timedatectl list-timezones | grep Budapest

Ha kiválasztottuk a megfelelő zónát, azt a set-timezone paranccsal állíthatjuk be. Fontos, hogy a helyes időzónát a rendszerben minél korábban beállítsuk, hiszen noha a naplóbejegyzésekhez az UTC kerül, a megjelenítés alapértelmezetten a helyi idővel történik, ami pedig az időzónától függ.

timedatectl set-timezone Europe/Budapest

Az aktuális idő adatait a status paranccsal tudjuk lekérdezni:

root@pnetlab:~# timedatectl status

               Local time: Sat 2023-06-17 19:25:08 CEST
           Universal time: Sat 2023-06-17 17:25:08 UTC
                 RTC time: Sat 2023-06-17 17:25:08
                Time zone: Europe/Budapest (CEST, +0200)
System clock synchronized: yes
              NTP service: n/a
          RTC in local TZ: no

A parancs kimenetében láthatjuk a helyi időt (Local time), az UTC időt (Universal Time), az RTC időt (Real-Time Clock), mely az alaplap órájának az ideje időzónától függetlenül, valamint az aktuális időzónát (Time zone). A kimenetből kiolvashatjuk, hogy a rendszeridő szinkronizálva van-e egy időszolgáltatóval (System clock synchronized), láthatjuk az NTP szolgáltatás beállítását (NTP service), valamit azt, hogy az RTC megfelel-e a helyi időnek (RTC in local TZ).


A szolgáltatás

Magának a naplózási szolgáltatásnak a neve a systemd-journald.service. Állapota a szokásos módon kérhető le:

root@pnetlab:~# systemctl status systemd-journald.service
● systemd-journald.service - Journal Service
     Loaded: loaded (/lib/systemd/system/systemd-journald.service; static; vendor preset: enabled)
     Active: active (running) since Sun 2023-06-11 10:01:12 CEST; 1 weeks 1 days ago
TriggeredBy: ● systemd-journald-dev-log.socket
             ● systemd-journald-audit.socket
             ● systemd-journald.socket
       Docs: man:systemd-journald.service(8)
             man:journald.conf(5)
   Main PID: 526 (systemd-journal)
     Status: "Processing requests..."
      Tasks: 1 (limit: 14203)
     Memory: 1012.8M
     CGroup: /system.slice/systemd-journald.service
             └─526 /lib/systemd/systemd-journald

A parancs kimenetéből kiolvasható, hogy a szolgáltatás engedélyezett, betöltésre került és aktív, és mióta fut. A TriggeredBy sorban azokat a socket-eket látjuk, amelyeken keresztül a systemd-journald megkapja a naplóbejegyzéseket. Láthatjuk még a szolgáltatáshoz tartozó dokumentáció hivatkozásait, a folyamatazonosítót (Main Pid), a folyamathoz tartozó futó feladatok számát (Tasks), az elfoglalt memóriát (Memory). A CGorup a szolgáltatás csoportját azonosítja. (A csoportelosztás a systemd egy olyan mechanizmusa, amely lehetővé teszi a folyamatok csoportosítását, és ezáltal az erőforrásokhoz való hozzáférésük szabályozását.)

Amikor a systemd naplóz akkor a naplófájlokat a konfigurációjától függően két helyen tudja kezelni: A futási idejű könyvtárban (/run/log/journal), és a /var/log/journal állandó jellegű könyvtárban. A futási idejű könyvtárban csak átmeneti jelleggel tárolja, és ez a rendszer újraindításakor törlődik. Az állandó tárhelyen viszont tovább is megmaradnak a bejegyzések. Ha egy naplófájl mérete elér egy meghatározott méretet, akkor átnevezi és nyit egy újat, ezzel akadályozva meg, hogy egy naplófájl mérete túl nagy legyen. (Ezt nevezzük a naplófájlok forgatásának, rotálásának.) Ügyeljünk arra, hogy a /var/log/journal könyvtárat a szolgáltatás nem hozza automatikusan létre, azt nekünk kell megtenni, egy esetleges törlés után.


A naplózás konfigurálása

A systemd.journald szolgáltatás konfigurációs beállításait a /etc/systemd/journald.conf állományban találjuk. A fontosabb beállítható paraméterek a következők:

  • Storage: Meghatározza azt a helyet, ahová a naplófájlok lementésre kerülnek. None esetén minden bejegyzés eldobásra, kerül, vagyis nincsen naplózás. Volatile esetén a naplóbejegyzések a memóriába, illetve a /run/log/jornal könyvtárba kerülnek, ahonnan újraindítás után törlődnek. Persistent beállításnál a /var/log/journal könyvtárba lesznek elmentve, ahol újraindítás után is megmaradnak. (Más beállítás hatására egy idő vagy méret után törlődhetnek innen is.) Az auto esetben általában a /var/log/journal könyvtárat használja, ha viszont ez nem létezik a /run/log/journal-t.
  • Compress: Itt adható meg, hogy egy küszöbérték felett az adatok tömörítve kerüljenek tárolásra.
  • SystemMaxUse: Meghatározza, hogy a merevlemezen mekkora helyet foglaljanak el összesen a naplófájlok.
  • SystemMaxFileSize: Egyetlen naplófájlnak ez lesz a maximális mérete a /var/log/journal-ban. Ha eléri, akkor új fájlba kezd.
  • RuntimeMaxFileSize: Ugyanaz, mint a SystemMaxFileSize, csak a /run/log/journal könyvtárra nézve.
  • SystemKeepFree: Itt adjuk meg, hogy mekkora szabad helyet hagyjon a /var/log/journal könyvtár kötetén a naplózás. Ha a naplófájlok mérete akkorára nő, hogy ennél kevesebb hely marad, akkor automatikusan törlésre kerülnek a régi bejegyzések.
  • RuntimeKeepFree: Ugyanaz, mint a SystemKeepfree, csak a /run/log/journal könyvtárra nézve.
  • ForwardToSyslog: Ha ez az érték yes (ez az alapértelmezett), akkor a journald a régi Syslog rendszernek is továbbítja a naplóbejegyzéseket, így azok a programok, amelyek a Syslog-on keresztül érték el a naplókat, továbbra is működni fognak.
  • MaxLevelStore: Itt adhatjuk meg azt a maximális prioritást, amellyel rendelkező üzenetek még beíródjanak a naplófájlba. (Az üzenetprioritásokról később még szó lesz.)

A naplóbejegyzések megjelenítésének alapjai

A systemd által összegyűjtött naplóbejegyzéseket a journalctl paranccsal tudjuk kilistázni:

root@pnetlab:~# journalctl

-- Logs begin at Mon 2023-05-08 02:52:21 CEST, end at Sat 2023-06-17 20:04:21 CEST. --
May 08 02:52:21 pnetlab multipathd[761]: sda: failed to get sysfs uid: Invalid argument
May 08 02:52:21 pnetlab multipathd[761]: sda: failed to get sgio uid: No such file or directory
May 08 02:52:25 pnetlab multipathd[761]: sdb: add missing path
May 08 02:52:25 pnetlab multipathd[761]: sdb: failed to get udev uid: Invalid argument
May 08 02:52:25 pnetlab multipathd[761]: sdb: failed to get sysfs uid: Invalid argument
May 08 02:52:25 pnetlab multipathd[761]: sdb: failed to get sgio uid: No such file or directory
May 08 02:52:26 pnetlab multipathd[761]: sda: add missing path
May 08 02:52:26 pnetlab multipathd[761]: sda: failed to get udev uid: Invalid argument
May 08 02:52:26 pnetlab multipathd[761]: sda: failed to get sysfs uid: Invalid argument
May 08 02:52:26 pnetlab multipathd[761]: sda: failed to get sgio uid: No such file or directory

Nagyon sok naplóbejegyzést láthatunk, lényegesebben többet, mint amit a hagyományos syslog volt képes összegyűjteni.
A parancs az egyes bejegyzéseknél az eseményekhez a helyi időt tartalmazó időbélyeget jelenítik meg. Amennyiben az UTC időt akarjuk látni, használjuk az utc flag-et:

journalctl --utc

A listában az egyes újraindításokat a — Reboot — sorok jelzik:

-- Logs begin at Mon 2023-05-08 02:52:21 CEST, end at Sun 2023-06-18 13:10:41 CEST. --
May 11 10:02:07 pnetlab login[224125]: ROOT LOGIN  on '/dev/tty1'
May 11 10:14:38 pnetlab blkdeactivate[234710]: Deactivating block devices:
May 11 10:14:38 pnetlab blkdeactivate[234710]:   [SKIP]: unmount of ubuntu--vg-ubuntu--lv (dm-0) mounted on /
-- Reboot --
May 11 11:15:24 pnetlab ovfstartup.sh[2018]: Running Virtual Environment...
May 11 11:15:24 pnetlab ovfstartup.sh[2018]: Check new disks
May 16 11:37:32 pnetlab blkdeactivate[3206023]: Deactivating block devices:
May 16 11:37:32 pnetlab blkdeactivate[3206023]:   [SKIP]: unmount of ubuntu--vg-ubuntu--lv (dm-0) mounted on /
-- Reboot --
May 16 12:38:27 pnetlab ovfstartup.sh[2008]: Running Virtual Environment...
May 16 12:38:27 pnetlab ovfstartup.sh[2008]: Check new disks
-- Reboot --
May 30 09:44:29 pnetlab ovfstartup.sh[2117]: Running Virtual Environment...
May 30 09:44:29 pnetlab ovfstartup.sh[2117]: Check new disks
-- Reboot --
Jun 05 09:02:26 pnetlab ovfstartup.sh[2134]: Running Virtual Environment...
Jun 05 09:02:26 pnetlab ovfstartup.sh[2134]: Check new disks
-- Reboot --
Jun 05 11:09:53 pnetlab ovfstartup.sh[2098]: Running Virtual Environment...
Jun 05 11:09:53 pnetlab ovfstartup.sh[2098]: Check new disks
Jun 11 10:01:00 pnetlab blkdeactivate[2931151]: Deactivating block devices:
Jun 11 10:01:00 pnetlab blkdeactivate[2931151]:   [SKIP]: unmount of ubuntu--vg-ubuntu--lv (dm-0) mounted on /
-- Reboot --
Jun 11 11:02:21 pnetlab ovfstartup.sh[2018]: Running Virtual Environment...
Jun 11 11:02:21 pnetlab ovfstartup.sh[2018]: Check new disks

A naplóbejegyzések szűrése idő alapján

A naplóbejegyzések alapértelmezetten dátumuk szerint növekvő sorrendbe jelennek meg, tehát elől látjuk a legrégebbi üzeneteket. Ha mi fordítva akarjuk, akkor a -r (–reverse) kapcsolót használhatjuk. Ilyenkor a legfrissebb naplóüzenetekkel kezdődik a lista. (Ilyenkor azonban az ok-okozati viszony is megfordul!)

journalctl -r

Sokszor van arra szükségünk, hogy csak bizonyos időtartományból származó naplóbejegyzéseket listázzunk ki. A -b kapcsolóval például a legutolsó rendszerindítás (boot) óta keletkezett naplóbejegyzéseket listázza ki:

journalctl -b

Lehetőségünk van a rendszer újraindítási alkalmait kilistázni a –list-boots kapcsolóval. Minden újraindításhoz egy-egy egyedi azonosítót (BOOT_ID) rendel a systemd, mely a lista 2. oszlopában jelenik meg.

root@pnetlab:~# journalctl --list-boots

-6 70af26a9557a4b24882e976011d15345 Mon 2023-05-08 02:52:21 CEST—Thu 2023-05-11 10:14:42 CEST
-5 6f861a9dcca6450388664eb5e668f37b Thu 2023-05-11 10:14:50 CEST—Tue 2023-05-16 11:37:37 CEST
-4 3e88e366c2974ddbbf9378506e587940 Tue 2023-05-16 11:37:44 CEST—Sun 2023-05-28 03:42:24 CEST
-3 c0bf5e1b8533441280cbada14cfd5024 Tue 2023-05-30 08:43:23 CEST—Wed 2023-05-31 23:12:48 CEST
-2 8d1b2a9fc1dd4e139700c36e18baf6d8 Mon 2023-06-05 08:01:20 CEST—Mon 2023-06-05 09:13:39 CEST
-1 8391ec1fa693498598de102b3ba2b600 Mon 2023-06-05 10:08:52 CEST—Sun 2023-06-11 10:01:05 CEST
 0 35ecd04660604cd3aaec238f0eaa8d1c Sun 2023-06-11 10:01:12 CEST—Sat 2023-06-17 21:55:23 CEST

A listából kiolvasható, hogy mikor indították és mikor állították le a rendszert, illetve a két újraindítás között eltelt idő is.

Bizonyos rendszerekben a systemd alapértelmezetten csak a legutolsó rendszerindítás óta eltelt időben keletkezett bejegyzéseket tárolja. Ha ezt tapasztalnánk, akkor a /etc/systemd/journald.conf fájlban állítsuk a Storage sort persistent-re.

Amennyiben a -b kapcsoló után megadjuk az egyik BOOT_ID-t, csak az ahhoz tartozó bejegyzések jelennek meg. Az első rendszerindítás eseményei például az így kapott listában olvashatók:

journalctl -b 70af26a9557a4b24882e976011d15345

Annak érdekében, hogy ne kelljen ezzel a hosszú azonosítóval dolgoznunk, sorszámokkal is megadhatjuk, melyik rendszerindításra vagyunk kíváncsiak. A -b -1 az eggyel korábbi, míg a -b 1 a legelsőt (legkorábbit) választja ki. (Vagyis negatív sorszámot megadva visszafelé, pozitív sorszámot megadva előrefelé lépdelünk.)

journalctl -b -1
journalctl -b 1

Természetesen lehetőségünk van arra is, hogy egy adott időtartományban keletkezett naplóbejegyzéseket jelenítsünk meg. Ehhez a –since, -S és –until, -U kapcsolókat használhatjuk, melyek után az időpontot többféle módon is megadhatjuk.

Listázzuk ki például a 2023. június 18. 6 óra 30 perc után keletkezett bejegyzéseket. Az időpontot YYYY-MM-DD HH:MM:SS formában adjuk meg.

journalctl --since "2023-06-18 06:30:00"

Ha az időpontból bizonyos részeket kihagyunk, akkor a rendszer alapértelmezett értékekkel helyettesíti. (Ha például kihagyjuk a dátumot, az aktuális dátum kerül behelyettesítésre, ha az időt, akkor 0 órától, ha a másodpercet, akkor 0 másodperctől kezdi a listát.)

Ha az időtartam végét is meg akarjuk adni, használjuk a –until opciót. Listázzuk ki például az előző példa időpontjától az első 1 percben keletkezett naplóbejegyzéseket:

journalctl --since "2023-06-18 06:30:00" --until "2023-06-18 06:31:00"

A journalctl képes olyan “emberi módon” megfogalmazott időtartományokat megérteni, mint a “tegnap”, “ma”, “1 órával ezelőttig”:

journalctl --since yesterday
journalctl --since today
journalctl --since 09:00 --until "1 hour ago"
journalctl --since "50 minutes ago"

(Az első két példa jelentése egyértelmű, míg az utolsóé a következő: Listázd ki a naplóbejegyzéseket ma 9 órától 1 órával ezelőttig bezáródóan.)


A bejegyzések szűrése szolgáltatások szerint

Amennyiben egy adott szolgáltatás által küldött naplóbejegyzésekre vagyunk kíváncsiak, a -u (unit) kapcsolót kell használnunk. Például az apache2 bejegyzései:

journalctl -u apache2.service

Természetesen ez kombinálható az idő alapú szűréssel. Például az apache2 mai napon keletkezett bejegyzéseinek listája (a .service utótag elhagyható):

journalctl -u apache2.service --since today

Ha például 2 folyamat összefügg, akkor mindkettő megadható, és időrendi sorrendben láthatjuk az általuk küldött üzeneteket:

journalctl -u apache2.service -u mysql.service --since today

Ha egy szolgáltatás gyermekszolgáltatásokat indít el, és ezeknek a gyermekszolgáltatásoknak az üzeneteire vagyunk kíváncsiak, akkor sokszor nem tudjuk megadni a nevüket. Ilyenkor a folyamatazonosítójukat (PID) használhatjuk. (A folyamatok azonosítóinak meghatározására többféle parancs is létezik, például a ps -e -o pid,cmd, top, htop.)

Határozzuk meg például az sshd-hez tartozó folyamatokat:

root@pnetlab:~# ps -e -o pid,cmd | grep sshd

   2058 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
3388875 sshd: balint [priv]
3388884 sshd: balint [priv]
3389018 sshd: balint@pts/0
3389074 sshd: balint@notty
3406292 grep --color=auto sshd

És listázzuk ki az egyikhez tartozó bejegyzéseket:

root@pnetlab:~# journalctl _PID=3388875

-- Logs begin at Mon 2023-05-08 02:52:21 CEST, end at Sun 2023-06-18 10:36:22 CEST. --
Jun 18 09:42:06 pnetlab sshd[3388875]: Accepted password for balint from 46.139.4.34 port 50661 ssh2
Jun 18 09:42:06 pnetlab sshd[3388875]: pam_unix(sshd:session): session opened for user balint by (uid=0)

Máskor arra van szükségünk, hogy egy adott felhasználóhoz vagy csoporthoz tartozó folyamatok bejegyzéseit láthassuk. Ezt az előzőhöz hasonlóan a _UID és _GID opciókkal tehetjük meg. Határozzuk meg például a www-data felhasználó azonosítóját, és kérjük le a hozzá tartozó bejegyzéseket:

root@pnetlab:~# id -u www-data
33

root@pnetlab:~# journalctl _UID=33
-- Logs begin at Mon 2023-05-08 02:52:21 CEST, end at Sun 2023-06-18 10:40:32 CEST. --
-- No entries --

A systemd a naplózás során számos információt tárol el a naplóbejegyzés mellett különböző mezőkben. Ezek egy részét a bejegyzést küldő folyamattól kapja meg, másik részét pedig saját maga gyűjti össze a rendszerből. Ilyen információ volt a folyamatazonosító is. Ha ezek alapján akarunk szűrni, akkor az információt tartalmazó mező azonosítóját kell megadnunk aláhúzással előtte (például a _PID, _UID, stb.) Ezeket a mezőazonosítókat ki is listázhatjuk a megfelelő man oldal megjelenítésével:

man systemd.journal-fields

A -F kapcsolóval egy adott mezőazonosító valamennyi értéke íratható ki. Ha például meg akarjuk állapítani, hogy milyen felhasználói azonosítók által indított folyamatok küldtek naplóbejegyzéseket, gépeljük be az alábbi parancsot:

root@pnetlab:~# journalctl -F _UID

104
103
0
997
100
114
1001

Arra a journalctl nem ad lehetőséget, hogy a felhasználók nevét lássuk az azonosítók helyett, de persze a megfelelő parancsok átirányításával erre is van lehetőség:

root@pnetlab:~# journalctl -F _UID | xargs -I {} sh -c 'id -nu {}'

syslog
messagebus
root
tomcat
systemd-network
ntp
balint

Noha nem tartozik közvetlenül a naplózáshoz, de értelmezzük lépésenként ezt az összetett parancsot:

  • journalctl -F _UID: Ez a journalctl parancs az előzőek szerint a naplóbejegyzésekhez kapcsolódó UID-ket kéri le, és ezeket a kimenetre irányítja.
  • |: Ez a pipe (csővezeték) operátor a journalctl kimenetét átirányítja a következő parancs bemenetére.
  • xargs -I {}: Az xargs parancs segítségével a journalctl kimenetét továbbítjuk a következő parancs bemenetére. A -I {} kapcsoló azt jelzi az xargs-nak, hogy a bemeneten kapott értéket a {} helyőrzővel helyettesítse, és ezt adja tovább a következő parancsnak. (Jelen esetben az sh-nak.) Az xargs tehát veszi egyenként a felhasználói azonosítókat, és továbbítja az sh-nak.
  • sh -c ‘id -nu {}’: Az sh paranccsal elindítjuk az alapértelmezett shell-t, és átadjuk neki végrehajtásra a -c kapcsoló után álló parancsot.
  • id -nu {}: Az id parancs megjeleníti a paraméterként kapott (itt a {}-on keersztül) azonosítójú felhasználó nevét.

A naplóbejegyzések lekérdezésében megadhatunk egy elérési utat, és minden olyan szolgáltatás, melynek elindításában megjelent ez az útvonal kilistáztatható:

journalctl /usr/bin/none

Ha a kernel által küldött üzenetek megjelenítése a cél, használjuk a -k vagy a –dmesg kapcsolót:

journalctl -k

Arra is lehetőség van, hogy a journalct közvetlenül regex kifejezéseket illesszen a bejegyzésekre, és ennek megfelelően szűrje azokat. A kifejezéseket a -g kapcsoló után kell megadni. A következő példában minden olyan bejegyzést látunk az aktuális boot-ban, melyben az error vagy a warning karaktersorozat szerepel:

journalctl -g "warning|error"

Naplóüzenetek szűrése prioritás szerint

A systemd által kezelt naplóüzenetek mindegyik egy-egy prioritással rendelkezik. A prioritás határozza meg egy üzenet (illetve az üzenetet kiváltó esemény) fontosságát, súlyosságát. A legelterjedtebb prioritási szintek:

0. Emergency (emerg): A rendszer azonnali beavatkozást igényel. (Súlyos hardverhiba vagy fontos rendszerkomponens hibája.)
1. Alert (alert): A rendszer azonnali figyelmet igényel. (Például adatvesztés közvetlen veszélye áll fent.)
2. Critical (crit): Kritikus hiba, amely komoly hatással lehet a rendszer működésére.
3. Error (err): Hibaüzenet, amely egy alkalmazás működésében fellépett hibát jelzi. Közvetlenül nem veszélyezteti a rendszer működését.
4. Warning (warning): Figyelmeztető üzenet, amely felhívja a figyelmet valamilyen lehetséges problémára.
5. Notice (notice): Olyan informatív üzenetek, amelyek jelzik az alkalmazások vagy a rendszer normális működését. (Például indítási, leállítási vagy konfigurációs események.)
6. Info (info): Olyan általános információk és jelentések, amelyek segítenek megérteni a rendszer működését vagy nyomon követni az eseményeket.
7. Debug (debug): Olyan részletes hibakeresési és hibajavítási információk, amelyek segítik a rendszerfejlesztőket és a fejlesztői csapatokat a problémák feltárásában és az alkalmazások finomhangolásában.

A legmagasabb prioritású az Emergency, a legalacsonyabb a Debug .A systemctl lehetőséget ad arra, hogy a rendszerüzeneteket a prioritásuk szerint szűrjük. Ha például megadjuk, hogy a megjelenített prioritási szint az Alert, akkor minden naplóbejegyzés megjelenik, amely Alert vagy Emergency prioritású. (Tehát a megadott prioritási szint és az attól magasabb prioritásúak jelennek meg.)

Jelenítsük meg az Error és az annál magasabb prioritású üzeneteket:

journalctl -p err

A naplóbejegyzések megjelenítésének testreszabása

Eddig azt tárgyaltuk, hogy mely naplóbejegyzések jelenjenek meg a képernyőn, most nézzük meg azt, hogyan módosíthatjuk ezen sorok megjelenítését.

Alapértelmezetten a systemctl a naplóbejegyzésekről olyan sok információt jelenít meg, hogy azok “kilógnak” a képernyő jobb oldalán. (A vízszintes kurzormozgató nyilakkal kell tologatni az ablakot jobbra-balra.) A –no-full kapcsolóval viszont rövidebb formában jeleníti meg a bejegyzéseket.

journalctl --no-full

Persze ettől ellentétes irányba is befolyásolhatjuk a megjelenítést. A -a kapcsolóval előírjuk, hogy a bejegyzés minden mezője jelenjen meg, tehát a hozzá tartozó valamennyi információt láthassuk.

journalctl -a

Alapértelmezetten a journalctl az üzeneteket oldalanként listázza ki, egy-egy billentyűlenyomással lapozhatunk előre. Ha szeretnénk egyben megkapni valamennyi sort (mert egy fájlba irányítjuk például), akkor használjuk a –no-pager kapcsolót:

journalctl --no-pager

A journalctl nem csak számunkra olvasható formában tudja kiírni a bejegyzéseket. A -o kapcsolóval számos más formátum is megadható. Ha például egy program json formában képes beolvasni az adatokat, akkor előírhatjuk ezt is:

root@pnetlab:~# journalctl -o json

{"_SOURCE_REALTIME_TIMESTAMP":"1683512453662268","_EXE":"/usr/lib/systemd/systemd","_CAP_EFFECTIVE":"0","USER_INVOCATION>
{"_SYSTEMD_UNIT":"multipathd.service","SYSLOG_IDENTIFIER":"multipathd","_EXE":"/usr/sbin/multipathd","SYSLOG_FACILITY":">
{"SYSLOG_FACILITY":"3","_CMDLINE":"/sbin/multipathd -d -s","_BOOT_ID":"70af26a9557a4b24882e976011d15345","_SYSTEMD_CGROU>
{"_COMM":"multipathd","_BOOT_ID":"70af26a9557a4b24882e976011d15345","_CMDLINE":"/sbin/multipathd -d -s","_HOSTNAME":"pne>
{"_EXE":"/usr/sbin/multipathd","__REALTIME_TIMESTAMP":"1683603180468866","__MONOTONIC_TIMESTAMP":"478637638527","_SYSTEM>

Ha olvashatóbban szeretnénk a json sorokat megjeleníteni, használjuk a json-pretty formátumot:

root@pnetlab:~# journalctl -b -u apache2 -o json-pretty
{
        "CODE_LINE" : "574",
        "PRIORITY" : "6",
        "__CURSOR" : "s=b5d379cdb41147cab19515de7e43117e;i=f05a2;b=35ecd04660604cd3aaec238f0eaa8d1c;m=66f1f3;t=5fdd6dc16>
        "_CAP_EFFECTIVE" : "1ffffffffff",
        "_GID" : "0",
        "UNIT" : "apache2.service",
        ...
}

Számos más formátum is létezik, a cat csak az üzeneteket, a verbose valamennyi mező értékét jeleníti meg, míg a short az alapértelmezett formátum.

Amennyiben a legutoljára generált üzeneteket szeretnénk látni, használjuk a -n vagy a –line kapcsolókat. Ezek a legutolsó 10 bejegyzést jelenítik meg alapértelmezetten. Ez a szám felülbírálható természetesen. Az alábbi parancs az aktuális boot apache2 által küldött utolsó bejegyzést jeleníti meg:

root@pnetlab:~# journalctl -b -u apache2 -n 1

-- Logs begin at Mon 2023-05-08 04:20:53 CEST, end at Mon 2023-06-19 12:40:55 CEST. --
Jun 19 00:00:06 pnetlab systemd[1]: Reloaded The Apache HTTP Server.

Amennyiben folyamatosan figyelni szeretnénk, milyen bejegyzések kerülnek a naplófájlba, használjuk a -f kapcsolót. A kipróbálásakor láthatjuk, ahogyan megjelennek az újabb és újabb üzenetek. (A parancs futása például a Ctrl-C-vel szakítható meg.)

journalctl -f

A naplófájlok karbantartása

Amennyiben szeretnénk tudni, hogy az eddigi naplóbejegyzések mekkora tárhelyet foglalnak el, használjuk a –disk-usage kapcsolót:

journalctl --disk-usage

Archived and active journals take up 4.0G in the file system.

A –vacuum-size kapcsolóval megadhatjuk, hogy a naplófájlok mérete mekkora legyen. A parancs addig törli a bejegyzéseket, amíg a fájlok által elfoglalt lemezterület mérete el nem éri a megadott értéket.

journalctl --vacuum-size=1G

Arra is van lehetőség, hogy egy adott időnél régebbi bejegyzéseket töröljünk. A következő parancs például az 1 évnél régebbi bejegyzéseket törli:

journalctl --vacuum-time=1years

Naplózás a szolgáltatások oldaláról

Ne felejtsük el, hogy a naplóüzeneteket alapvetően az egyes szolgáltatások küldik, mégpedig úgy, ahogyan a szolgáltatás fejlesztői ezt meghatározták. Minden üzenethez egy prioritás (0-tól 7-ig) van rendelve, és általában a szolgáltatások konfigurációs fájljában lehet azt meghatározni, hogy milyen prioritástól (szinttől) kezdve küldjék el az üzeneteket.

Az apache2 konfigurációs állományában például a következő lehetőségek állnak rendelkezésünkre:

Az ErrorLog direktívával meghatározhatod az Apache hibaüzenetek naplófájljának elérési útvonalát és egyéb paramétereit. Például a hibanapló helye:

ErrorLog /var/log/apache2/error.log

CustomLog direktívával konfigurálhatod a hozzáférési naplózási bejegyzéseket. (Ide kerülnek azok a naplóbejegyzések, amelyek információkat tartalmaznak a kliensek által a szolgáltatásra tett kérésekről és a szerver válaszairól.) Meghatározhatod az elérési útvonalat és a naplóformátumot. A combined kulcsszó a naplóbejegyzések egy nagyon gyakran használt formátumát írja elő.

CustomLog /var/log/apache2/access.log combined

Egy naplóbejegyzés formátuma formázó karakterekkel állítható összes. Ahhoz, hogy egy kicsit belelássunk a logikájába, vizsgáljuk meg, hogy a combined üzenetformátumának összetételét:

  • %h: A kliens IP-címe vagy a kliens hostname
  • %l: A kliens hitelesítőnevét (ha elérhető)
  • %u: A hitelesített felhasználói név (ha van)
  • %t: A kérés beérkezésének időpontja
  • %r: A teljes HTTP kérés, beleértve a módszert (GET, POST stb.), az URL-t és a protokollt.
  • %>s: A szerver válaszának státuszkódja
  • %b: A válasz mérete
  • %{Referer}i: A hivatkozás (Referer) fejléc értéke (innen navigált át a felhasználó a kért oldalra)
  • %{User-Agent}i: A kliens felhasználói ügynök (User-Agent) fejléc értéke (ezzel azonosíthatjuk a kliens oldali alkalmazást)

Egyéni naplóbejegyzés formátumot bármikor mi is összeállíthatunk. Ha például az Apache kérés- és válaszfejlécek rögzítését is szeretnénk, ehhez az Apache konfigurációs fájlban engedélyezhetjük a mod_log_headers modult definiálunk egy speciális naplóformátumot. A konfigurációs fájlban ez így jelenik meg:

LoadModule log_headers_module modules/mod_log_headers.so
CustomLog /var/log/apache2/access.log combined
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" forwarded
CustomLog /var/log/apache2/access.log forwarded

És természetesen azt is beállíthatjuk, hogy a milyen szinttől kezdve küldje az üzeneteket a szolgáltatás. (Vigyázzunk arra, hogy ha a systemd-journald szolgáltatásban magasabb szint van meghatározva, mint a szolgáltatásnál, akkor a szolgáltatás naplófájljaiba több bejegyzés kerül, mint a journal-ba. Például az apache2 a warn (4-es) szinttől küld, a journald viszont error-tól (3-as) küld, akkor az apache2 naplóiba a 4-3-2-1-0 szintű üzenetek kerülnek be, a journal-ba viszont csak a 3-2-1-0). És persze fordítva is ez problémát okoz.)

LogLevel warn

Naplóüzenetek küldése

A hagyományos linuxos naplózó rendszerekben a logger parancsot használták naplóüzenetek generálására. Ez nem függ a systemd-től. Nézzünk pár példát a használatára:

logger "Ez egy naplóüzenet"
logger -p user.warning "Ez egy warning prioritású naplóüzenet."
logger -t myapp "Ez a myapp alkalmazás által küldött naplóüzenet."
logger -f naplo.txt

Az első egy sima naplóüzenetet küld, a második már prioritást is rendel hozzá, a harmadik felcímkézi, hogy melyik alkalmazás küldte, míg a negyedik egy fájl tartalmát küldi el naplóüzenetként.

Az következő két példában korlátozhatjuk a naplóbejegyzések hosszát. Az első az üzenetből csak az első 5 karaktert küldi el, míg a második a fájlt 5 byte-os darabokra vágja, és mindegyiket külön üzenetként küldi tovább. (Vagyis a –size másképpen működik egy karaktersorozatra, mint egy fájlra.)

logger --size 5 "Ez egy hosszabb naplóüzenet!"
logger --size 5 -f naplo.txt

A systemd által kezelt naplózáshoz egy új parancsot fejlesztettek ki, a systemd-cat-et, melybe átirányíthatunk egy kimenetet, és az továbbítja a naplóba. A -t kapcsolóval megadhatjuk azt a címkét, amellyel ellátja az naplóbejegyzést.

echo "Ez az üzenet a naplóban megjelenik" | systemd-cat -t sajat-uzenet

root@pnetlab:~# journalctl -b -g "üzenet"
-- Logs begin at Tue 2023-05-09 16:37:06 CEST, end at Tue 2023-06-20 20:10:49 CEST. --
Jun 20 20:10:29 pnetlab sajat-uzenet[372591]: Ez az üzenet a naplóban megjelenik

Az alábbi szkript pedig leellenőrzi, hogy fut-e az apache szolgáltatás, és ha igen, a naplóba feljegyzi ezt az eseményt:

#!/bin/none

# Ellenőrizzük az Apache szolgáltatás állapotát
if systemctl is-active --quiet apache2; then
    # Az Apache fut, írjunk üzenetet a systemd-journald-nak
    echo "Az Apache szolgáltatás fut." | systemd-cat -t apache-status
else
    echo "Az Apache szolgáltatás nem fut."
fi

A cikkben szereplő példákban közvetlenül root felhasználóként bejelentkezve adjuk ki a parancsokat azért, hogy az állandó sudo használata ne vonja el a figyelmet magáról a parancsok használatáról. Felhívjuk a figyelmet viszont arra, hogy éles rendszerekben biztonsági szempontokból a sudo használata erősen ajánlott!

This will close in 20 seconds