Шпаргалка по systemd journald (journalctl): базовые случаи, грабли на свежем OpenSSH и рецепт получения текстового лога из журнала без rsyslog.
# логи конкретного сервиса (unit) — основной режим
journalctl -u ssh
journalctl -u ssh -f # follow (как tail -f)
journalctl -u ssh -n 100 # последние 100 строк
journalctl -u ssh -r # обратный порядок (свежие сверху)
# окно по времени
journalctl -u ssh --since "-1h" # за последний час
journalctl -u ssh --since today
journalctl -u ssh -S "2026-06-01 00:00:00" # -S = --since (явная дата)
journalctl -u ssh -S "Jun 01 00:00:00" -U "Jun 02 00:00:00" # -U = --until
# загрузки
journalctl -b # текущая загрузка
journalctl -b -1 # предыдущая загрузка
journalctl --list-boots
# фильтры
journalctl -p err # по приоритету (err и выше)
journalctl -k # ядро (аналог dmesg)
journalctl _PID=1234
journalctl _SYSTEMD_UNIT=ssh.service
# форматы вывода
journalctl -u ssh -o short-iso # ISO-таймстамп
journalctl -u ssh -o cat # только текст сообщения
journalctl -u ssh -o json # JSON (для парсинга полей _COMM, _PID и т.п.)
# обслуживание журнала
journalctl --disk-usage
journalctl --vacuum-time=7d # удалить записи старше 7 дней
journalctl --vacuum-size=1G
_COMM=sshd vs -u ssh (OpenSSH 9.8+)На свежем OpenSSH (9.8+, Debian 13 / Proxmox VE 9) демон разделён на процессы: слушатель sshd и per-connection sshd-session (+ sshd-auth).
journalctl _COMM=sshd ловит только слушателя — там лишь общие строки вроде Timeout before authentication.Invalid user …, Failed password …, Accepted publickey …) пишет **sshd-session** с другим _COMM → при фильтре _COMM=sshd они теряются (видно 0!).Правильно — фильтровать по unit'у (он включает все процессы службы):
# НЕВЕРНО на OpenSSH 9.8+: теряет sshd-session
journalctl _COMM=sshd --since "-6h" | grep -c "Invalid user" # -> 0
# ВЕРНО: весь unit = полный auth-лог (как в /var/log/auth.log)
journalctl -u ssh --since "-6h" | grep -c "Invalid user" # -> реальное число
Вывод: для чтения SSH-событий из журнала всегда journalctl -u ssh, не _COMM=sshd.
Зачем: некоторым потребителям нужен файловый лог (например, Zabbix-item log[] умеет читать только файлы), а на journald-only системах (Debian 12+/Proxmox VE 8+) текстовых /var/log/auth.log / secure нет, и ставить полноценный rsyslog нежелательно (для Proxmox это legacy + двойное логирование).
Решение — лёгкий systemd-сервис, тейлящий журнал нужного unit'а в текстовый файл. По сути «мини-syslog на один unit».
/etc/systemd/system/ssh-journal-to-file.service:
[Unit]
Description=Tail sshd journal to text file (for file-based log consumers)
After=ssh.service systemd-journald.service
[Service]
# создать файл с правами, читаемыми группой adm (туда входит zabbix)
ExecStartPre=-/usr/bin/touch /var/log/ssh-journal.log
ExecStartPre=-/usr/bin/chown root:adm /var/log/ssh-journal.log
ExecStartPre=-/usr/bin/chmod 0640 /var/log/ssh-journal.log
# -u ssh = весь unit (включая sshd-session); -n 0 -f = без бэкфилла, только новое
ExecStart=/usr/bin/journalctl -u ssh -f -n 0 -o short
StandardOutput=append:/var/log/ssh-journal.log
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
/etc/logrotate.d/ssh-journal (процесс держит файл открытым → нужен copytruncate):
/var/log/ssh-journal.log {
daily
rotate 7
missingok
notifempty
compress
delaycompress
copytruncate
su root adm
}
Запуск и проверка:
systemctl daemon-reload
systemctl enable --now ssh-journal-to-file.service
systemctl is-active ssh-journal-to-file.service
ls -l /var/log/ssh-journal.log # ожидаем root:adm 0640
tail -f /var/log/ssh-journal.log
Нюансы:
StandardOutput=append: (systemd ≥ 240) пишет stdout сервиса прямо в файл — без шелл-редиректа и кавычек в unit'е.copytruncate имеет микрогонку при ротации (пара строк может потеряться в момент копирования) — для счётчиков/мониторинга некритично.root:adm 0640 — чтобы читатель (например пользователь zabbix, состоящий в группе adm) мог читать файл, не открывая его всему миру.ExecStart именно -u ssh, не _COMM=sshd (см. раздел выше про OpenSSH 9.8+).