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.
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í:
- Signál k znovuotevření – nginx reaguje na
USR1, mnoho démonů naHUP. To je čisté řešení, ale aplikace ho musí podporovat. (SignálUSR1v 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 poUSR1mohly ukončit.) 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/, maxsizeu logů, které můžou náhle narůst,- journald má
SystemMaxUse, - na rotaci jste otestovali
logrotate -da-f.