Servery a DevOps

Logy na Linux serveru: logrotate a limity pro journald

Kde hledat logy, jak nastavit logrotate pro vlastní aplikaci, co znamená copytruncate a postrotate, a jak omezit velikost systemd journalu.

12. 10. 2026 · 4 min čtení

Logy jsou první místo, kam se díváte při problému – a zároveň častý důvod, proč se zaplní disk. Aplikace, která rok zapisuje do jednoho souboru bez rotace, klidně vytvoří desítky gigabajtů. Ukážeme si, kde logy hledat a jak je udržet pod kontrolou.

Kde logy najdete

Na Ubuntu existují dva systémy vedle sebe:

systemd journal – binární úložiště, čtete ho přes journalctl. Sem jde výstup všech systemd služeb i jádra.

Textové soubory v /var/log/:

Soubor Obsah
/var/log/syslog obecné systémové zprávy (přeposílá rsyslog)
/var/log/auth.log přihlášení, sudo, SSH
/var/log/kern.log zprávy jádra
/var/log/nginx/access.log, error.log webový server
/var/log/apt/history.log historie instalací
/var/log/unattended-upgrades/ automatické aktualizace

Co zabírá nejvíc místa:

sudo du -sh /var/log/* | sort -h | tail
journalctl --disk-usage

Jak funguje logrotate

logrotate pravidelně (na Ubuntu denně přes logrotate.timer) přejmenuje aktuální log, např. app.log → app.log.1, starší komprimuje a nejstarší maže. Konfigurace:

  • /etc/logrotate.conf – globální výchozí hodnoty,
  • /etc/logrotate.d/ – soubor pro každou aplikaci (nginx, apt, rsyslog …).

Například nginx v Ubuntu má /etc/logrotate.d/nginx s denní rotací a 14 uchovanými soubory.

Konfigurace pro vlastní aplikaci

Vaše aplikace zapisuje do /var/log/mojeapp/*.log. Vytvořte /etc/logrotate.d/mojeapp:

/var/log/mojeapp/*.log {
    daily
    rotate 14
    maxsize 100M
    missingok
    notifempty
    compress
    delaycompress
    create 0640 mojeapp adm
    sharedscripts
    postrotate
        systemctl kill -s USR1 mojeapp.service >/dev/null 2>&1 || true
    endscript
}
Direktiva Význam
daily / weekly jak často rotovat
rotate 14 kolik starých souborů uchovat
maxsize 100M rotovat dřív, pokud log přeroste velikost (kontroluje se jen při běhu logrotate)
missingok nevadí, když soubor neexistuje
notifempty prázdný log nerotovat
compress + delaycompress gzip, ale nejnovější rotovaný soubor nechat nekomprimovaný
create 0640 user group nový prázdný log s danými právy
sharedscripts postrotate spustit jednou pro všechny soubory, ne pro každý
postrotate příkaz po rotaci – typicky signál aplikaci, aby znovu otevřela soubor

Proč postrotate (nebo copytruncate)

Proces má log otevřený přes souborový deskriptor. Když logrotate soubor přejmenuje, aplikace dál zapisuje do přejmenovaného souboru app.log.1. Dvě řešení:

  1. Signál k znovuotevření – nginx reaguje na USR1, mnoho démonů na HUP. To je čisté řešení, ale aplikace ho musí podporovat. (Signál USR1 v příkladu výše je jen ilustrace – ověřte, jaký signál vaše aplikace očekává. Node.js nebo Python bez vlastní obsluhy signálu by se po USR1 mohly ukončit.)
  2. copytruncate – logrotate obsah zkopíruje a původní soubor zkrátí na nulu. Funguje vždy, ale mezi kopií a zkrácením můžete ztratit pár řádků. Aplikace musí soubor otevírat v režimu append (O_APPEND), jinak vznikne soubor s „dírou“ plnou nul.
/var/log/mojeapp/*.log {
    daily
    rotate 7
    compress
    missingok
    copytruncate
}

Testování

Nejdřív nanečisto (nic se nezmění):

sudo logrotate -d /etc/logrotate.d/mojeapp

Vynucená rotace pro ověření, že vše funguje:

sudo logrotate -f /etc/logrotate.d/mojeapp
ls -lh /var/log/mojeapp/

Stav posledních rotací je v /var/lib/logrotate/status. Logrotate odmítne pracovat v adresáři zapisovatelném pro skupinu nebo ostatní – v takovém případě přidejte direktivu su mojeapp mojeapp.

Jednodušší cesta: logujte do journalu

Pokud aplikace běží jako systemd služba, nemusí vůbec psát do souborů. Stačí vypisovat na stdout/stderr a journald se postará o ukládání, rotaci i vyhledávání:

journalctl -u mojeapp --since today -p warning

Odpadá konfigurace logrotate i problém s otevřenými deskriptory.

Limit velikosti journalu

Ve výchozím stavu journald zabere až 10 % souborového systému (maximálně 4 GB). Na malém VPS je to zbytečně moc. Vytvořte /etc/systemd/journald.conf.d/size.conf:

[Journal]
SystemMaxUse=500M
MaxRetentionSec=1month
sudo systemctl restart systemd-journald

Jednorázové vyčištění:

sudo journalctl --vacuum-size=300M
sudo journalctl --vacuum-time=14d

Smazaný log, místo se neuvolnilo

Klasická past: smažete obří log přes rm, ale df ukazuje stále plný disk. Proces má soubor dál otevřený a místo se uvolní, až ho zavře.

sudo lsof +L1 | grep -i log

Řešení je restart dané služby. Příště soubor místo mazání zkraťte:

sudo truncate -s 0 /var/log/mojeapp/app.log

Kontrolní seznam

  • každá aplikace s vlastními log soubory má záznam v /etc/logrotate.d/,
  • maxsize u logů, které můžou náhle narůst,
  • journald má SystemMaxUse,
  • na rotaci jste otestovali logrotate -d a -f.