Short answer: journalctl -u SERVICE shows one service’s log, -f follows it live, --since "1 hour ago" limits the time, -p err shows only errors, -b limits it to the current boot and --grep PATTERN searches. journalctl --disk-usage shows how much space the journal uses, and journalctl --vacuum-time=14d deletes older entries. If /var/log/journal does not exist, the journal is lost at every reboot: create it with mkdir -p /var/log/journal, then run systemd-tmpfiles --create --prefix /var/log/journal and journalctl --flush.
Applies to systemd 252 on AlmaLinux 9.8 (cPanel 138, DirectAdmin 1.712) and Debian 12; lab test 11 Oct 2026
We ran every command on this page on our lab servers on 11 October 2026: systemd 252 on AlmaLinux 9.8 (cPanel 138 and DirectAdmin 1.712) and on Debian 12. The outputs shown are from those servers, shortened. Note that the SSH service is sshd on AlmaLinux and ssh on Debian.
Table of Contents
journalctl quick reference
| Task | Command |
|---|---|
| Newest entries, jump to the end | journalctl -e |
| Last 50 lines, no pager | journalctl -n 50 --no-pager |
| Follow live (like tail -f) | journalctl -f |
| One service | journalctl -u exim |
| Several services together | journalctl -u sshd -u dovecot |
| Time range | journalctl --since "2026-10-11 03:00" --until "2026-10-11 03:05" |
| Relative time | journalctl --since "1 hour ago" or --since today |
| Errors and worse | journalctl -p err -b |
| Warnings to errors only | journalctl -p warning..err |
| Kernel messages | journalctl -k |
| Previous boot | journalctl -b -1 (needs a persistent journal) |
| List boots | journalctl --list-boots |
| By program name (syslog tag) | journalctl -t CROND |
| By process ID or user ID | journalctl _PID=1234, journalctl _UID=0 |
| Search text (regex) | journalctl -u sshd --grep "Invalid user" |
| Newest first | journalctl -r |
| Message text only | journalctl -o cat |
| ISO timestamps | journalctl -o short-iso |
| All fields as JSON | journalctl -n 1 -o json-pretty |
| Which values a field has | journalctl -F _SYSTEMD_UNIT |
| Disk usage | journalctl --disk-usage |
| Delete old entries | journalctl --vacuum-time=14d or --vacuum-size=500M |
| Check for corruption | journalctl --verify |
Filter by service, program and process
-u takes a systemd unit name. Find the right one with systemctl list-units --type=service. On our labs the useful units were:
| Server | Units we used |
|---|---|
| cPanel 138 (AlmaLinux 9) | sshd, exim, dovecot, httpd, mariadb, pdns |
| DirectAdmin 1.712 (AlmaLinux 9) | directadmin, exim, httpd, php-fpm83, php-fpm74 (one per PHP version) |
| Debian 12 | ssh, cron, apache2, chrony |
Some messages do not belong to a service. Cron jobs on AlmaLinux are logged with the tag CROND, so journalctl -t CROND finds them; on Debian the tag is cron. To see which tag a line uses, print one entry as JSON and look at SYSLOG_IDENTIFIER:
journalctl -n 1 -o json-pretty | grep -E '"(_SYSTEMD_UNIT|SYSLOG_IDENTIFIER|_COMM|PRIORITY)"'
"_SYSTEMD_UNIT" : "sshd.service",
"SYSLOG_IDENTIFIER" : "sshd-session",
"_COMM" : "sshd-session",
"PRIORITY" : "6",
On AlmaLinux 9.8 the SSH login lines come from sshd-session, not sshd, so -t sshd misses them. -u sshd catches both.
Filter by time and boot
journalctl --since today
journalctl --since "1 hour ago"
journalctl --since "2026-10-11 03:00" --until "2026-10-11 03:05"
journalctl -b # this boot
journalctl -b -1 # the boot before
journalctl --list-boots
On our cPanel lab, journalctl -b -1 printed Specifying boot ID or boot offset has no effect, no persistent journal was found. That server kept its journal only in memory, so older boots were gone. See making the journal survive a reboot.
Errors only: priority levels
-p filters by syslog priority: emerg (0), alert (1), crit (2), err (3), warning (4), notice (5), info (6), debug (7). A single level means that level and everything more serious; a range like warning..err shows only that band.
journalctl -p err -b --no-pager | tail
journalctl -p warning..err --since today --no-pager | wc -l # 179 lines on our cPanel lab
Expect noise. On our cPanel lab, most of the err lines came from a single Python traceback that repeated.
Search the journal
--grep takes a regular expression and only works if journalctl was built with PCRE2. Both our AlmaLinux 9.8 and Debian 12 builds were (journalctl --version shows +PCRE2). It is case-insensitive unless the pattern has capitals; --case-sensitive changes that.
journalctl -u sshd --since "-24h" --grep "Invalid user" -n 2
journalctl -u sshd --since "-24h" --no-pager | grep -c "Failed password\|Invalid user" # 1,398 on our cPanel lab
# Top attacking IPs in the last 24 hours
journalctl -u sshd --since "-24h" -o cat | grep -E "Failed password|Invalid user" \
| grep -oE "from [0-9a-f.:]+" | sort | uniq -c | sort -rn | head
That count shows why SSH should not answer password logins from the whole internet: see harden SSH on AlmaLinux 9 and fail2ban vs CSF.
Follow logs live
journalctl -f # everything
journalctl -fu exim # one service
journalctl -f -u sshd -u dovecot # two services
journalctl -f -p err # only new errors
Stop with Ctrl+C. Inside a script, use timeout 60 journalctl -f ... so it ends by itself.
Output formats
| Option | Gives you |
|---|---|
-o short (default) | Syslog-style lines |
-o short-iso | 2026-10-11T05:38:56-0500 lab1 sshd-session[643164]: ... |
-o cat | The message text only, good for grep and awk |
-o json / json-pretty | Every field, for scripts and log shippers |
-o verbose | Every field in readable form |
--utc | Timestamps in UTC instead of the server’s time zone |
-x | Adds explanations from the message catalogue where available |
Make the journal survive a reboot
With the default Storage=auto, journald stores logs on disk only if /var/log/journal exists; otherwise it keeps them in /run/log/journal, in memory, and they are lost at reboot. Our DirectAdmin and Debian labs had the directory. Our cPanel lab (an AlmaLinux 9.8 cloud image) did not, so every reboot erased its logs. That server had no rsyslog either, so there was no other copy.
ls -d /var/log/journal || echo "journal is NOT persistent"
mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal
journalctl --flush # move what is in memory to disk
journalctl --disk-usage
On our lab, journalctl --flush moved 73 MB from /run/log/journal to /var/log/journal straight away. No restart was needed. An alternative is to set Storage=persistent in a drop-in file (below).
Limit the journal’s size
Put limits in a drop-in file instead of editing /etc/systemd/journald.conf, so updates do not overwrite them:
mkdir -p /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/limits.conf <<'EOF'
[Journal]
SystemMaxUse=200M
MaxRetentionSec=14day
EOF
systemctl restart systemd-journald
systemd-analyze cat-config systemd/journald.conf | grep -v '^#' # check the merged result
These are the limits our labs run with. SystemMaxUse caps the disk journal (the default is 10% of the file system, up to 4 GB). MaxRetentionSec drops entries older than the given age. To free space immediately:
journalctl --vacuum-size=500M
journalctl --vacuum-time=14d
journalctl --rotate # close the active files first so they can be vacuumed too
Vacuuming only removes archived journal files. If it says freed 0B, as it did on our labs, everything was already within the limits.
journalctl and the text log files
If rsyslog is installed, the same messages are also written to /var/log/messages, secure and maillog (AlmaLinux), or /var/log/syslog and auth.log (Debian). Debian 12 and many AlmaLinux 9 cloud images do not install rsyslog, so journalctl is the only way in. For which logs exist on cPanel and DirectAdmin, see Linux server log file locations. Exim, Apache domain logs and the panels’ own logs are separate files that journalctl does not show.
Frequently asked questions
How do I see the logs of one service with journalctl?
Run journalctl -u followed by the unit name, for example journalctl -u exim. Add -f to follow it live, -n 100 for the last 100 lines, or --since "1 hour ago" to limit the time.
How do I follow logs in real time with journalctl?
Run journalctl -f, or journalctl -fu SERVICE for one service. It works like tail -f; stop it with Ctrl+C.
Why does journalctl -b -1 show nothing?
The journal is not persistent, so earlier boots are not kept. Create /var/log/journal, run systemd-tmpfiles --create --prefix /var/log/journal and journalctl --flush; from then on previous boots are kept.
How do I reduce the size of the systemd journal?
Run journalctl --vacuum-size=500M or journalctl --vacuum-time=14d to delete old archived files now. Set SystemMaxUse and MaxRetentionSec in /etc/systemd/journald.conf.d/ to keep it small, then restart systemd-journald.
How do I show only errors in journalctl?
Use -p err, for example journalctl -p err -b for errors since the last boot. -p warning..err shows warnings and errors only.
Reading a lot of our guides? Go ad-free with srvScripts Pro for $6 a month. It also pays for new guides. Cancel any time.