journalctl command: usage, logs by service and cleaning up journal size

Test environmentRHEL familyAlmaLinux 9.8systemd 252root accountDebian 12 regular accountChecked 2026-11-05
System info · settings commandsjournalctlLocation/usr/bin/journalctl

The journalctl command is the tool for picking out and reading the logs that services and the kernel leave in the systemd journal. On Linux systems that use systemd, systemd-journald collects these logs into the journal. Reading logs by service, time and priority on an AlmaLinux 9 server and a Debian 12 server showed that a regular account sees only its own logs, and that a server keeping its journal in memory cannot select a previous boot.

The output below comes from the two servers. Host names, accounts, boot IDs, process numbers on the AlmaLinux server and the systemd package release were replaced with example values, and both servers printed times in UTC.

1️⃣ How to use the journalctl command and read recent logs

Running journalctl without options opens the journal in less starting from its oldest line, so to see recent logs set the number of lines with -n. If you leave out the number after -n, you get 10 lines.

journalctl -n 3
Oct 28 07:14:06 server1 systemd[1]: session-3017.scope: Deactivated successfully.
Oct 28 07:14:06 server1 systemd[1]: session-3017.scope: Consumed 3.934s CPU time.
Oct 28 07:14:07 server1 sudo[851987]: pam_unix(sudo:session): session closed for user user

Each line consists of the time, the host name, the program that wrote the log with its process number, and the message. Adding -r reverses the order so the most recent line comes to the top. In the crond log on the AlmaLinux server, the CMDEND line written last was at the top.

journalctl -r -u crond -n 3
Oct 28 07:01:01 server1 CROND[841384]: (root) CMDEND (run-parts /etc/cron.hourly)
Oct 28 07:01:01 server1 run-parts[841394]: (/etc/cron.hourly) starting 0anacron
Oct 28 07:01:01 server1 CROND[841388]: (root) CMD (run-parts /etc/cron.hourly)

-f does not exit after printing the last line and keeps printing new lines as they arrive. On the Debian 12 server, the last logger line was left on screen with -q and -t myapp, and two more lines were written with logger. The two lines appeared right below it.

journalctl -q -f -n 1 -t myapp
Oct 28 07:12:46 server2 myapp[347704]: journalctl error test
Oct 28 07:14:35 server2 myapp[347881]: follow line 1
Oct 28 07:14:36 server2 myapp[347877]: follow line 2

-f does not stop until you press Ctrl+C, so use it to watch the log while a service restarts.

In less, lines wider than the screen are cut off on the right, and you see the cut part with the arrow keys. Output sent to a pipe or a file does not go through less. To print straight to the terminal without less, add --no-pager.

2️⃣ journalctl logs by service

Recent lines mix logs from many services, so to see the log of one service, give the unit name with -u. The .service at the end of the unit name can be left out.

journalctl -u crond -n 4
Oct 28 06:01:01 server1 CROND[802926]: (root) CMDEND (run-parts /etc/cron.hourly)
Oct 28 07:01:01 server1 CROND[841388]: (root) CMD (run-parts /etc/cron.hourly)
Oct 28 07:01:01 server1 run-parts[841394]: (/etc/cron.hourly) starting 0anacron
Oct 28 07:01:01 server1 CROND[841384]: (root) CMDEND (run-parts /etc/cron.hourly)

Writing -u twice mixes the logs of two services in time order. Selecting crond and nginx together from 08:00 to 08:15 on October 18 on the AlmaLinux server gave four crond lines at 08:01 followed by two nginx reload lines at 08:12.

journalctl -u nginx -u crond --since '2026-10-18 08:00' --until '2026-10-18 08:15'
Oct 18 08:01:01 server1 CROND[381522]: (root) CMD (run-parts /etc/cron.hourly)
Oct 18 08:01:01 server1 run-parts[381528]: (/etc/cron.hourly) starting 0anacron
Oct 18 08:01:01 server1 run-parts[381534]: (/etc/cron.hourly) finished 0anacron
Oct 18 08:01:01 server1 CROND[381518]: (root) CMDEND (run-parts /etc/cron.hourly)
Oct 18 08:12:30 server1 systemd[1]: Reloading nginx - high performance web server...
Oct 18 08:12:30 server1 systemd[1]: Reloaded nginx - high performance web server.

systemctl status prints only the last 10 log lines under the service status, so check older logs with journalctl -u. Right after you run systemctl restart on a service, run journalctl -u to check the startup log.

Logs that scripts or cron jobs wrote with logger are found by their tag (identifier), not by a unit. After -t, write the same name that was given to logger's -t.

logger -t myapp 'journalctl test message'

On the Debian 12 server, logger printed nothing on screen, and the lines it wrote were found with -t myapp.

journalctl -q -t myapp
Oct 28 07:12:44 server2 myapp[347693]: journalctl test message

-g keeps only the lines whose message contains certain text. If you write the text all in lowercase, the match ignores case.

journalctl -u crond -g anacron -n 2
Oct 28 07:01:01 server1 run-parts[841394]: (/etc/cron.hourly) starting 0anacron

-n counts lines before -g filters them, so of the last two crond lines only the one containing anacron remained.

3️⃣ Logs by time range and by boot

--since and --until set the start and end of the time range to print. If there is a space between the date and the time, wrap the value in single quotes.

--since valueMeaning and when to use it
'2026-10-28 06:00'From 06:00:00 that day (seconds default to 00 if omitted), when you know when the problem started
todayFrom 00:00:00 today, to see only today's logs
yesterdayFrom 00:00:00 yesterday until now; add --until today to see only yesterday
'-2h'From 2 hours ago, to see what just happened (measured below)
'1 hour ago'From 1 hour ago, same as -1h

On the AlmaLinux server, the last 2 hours started with the crond lines written at 06:01; below are the first four of them.

journalctl -u crond --since '-2h' | head -4
Oct 28 06:01:01 server1 CROND[802930]: (root) CMD (run-parts /etc/cron.hourly)
Oct 28 06:01:01 server1 run-parts[802936]: (/etc/cron.hourly) starting 0anacron
Oct 28 06:01:01 server1 CROND[802926]: (root) CMDEND (run-parts /etc/cron.hourly)
Oct 28 07:01:01 server1 CROND[841388]: (root) CMD (run-parts /etc/cron.hourly)

-b keeps only logs since the current boot. When looking for why a server restarted, first check the boot list to see whether logs from the previous boot remain.

journalctl -b -u crond -n 2
Oct 28 07:01:01 server1 run-parts[841394]: (/etc/cron.hourly) starting 0anacron
Oct 28 07:01:01 server1 CROND[841384]: (root) CMDEND (run-parts /etc/cron.hourly)

--list-boots prints, for each boot kept in the journal, its number, boot ID, and the times of its first and last lines.

journalctl --list-boots
IDX BOOT ID                          FIRST ENTRY                 LAST ENTRY
  0 4f1c2a9be0d34c7a8e6b5d20c1f3a7e9 Sat 2026-10-17 08:29:26 UTC Wed 2026-10-28 07:16:10 UTC

The AlmaLinux server does not keep its journal on disk, so it had only one boot record. Because of that, -b -1 for the previous boot only printed a notice and ended.

journalctl -b -1
Specifying boot ID or boot offset has no effect, no persistent journal was found.

Logs from a previous boot can be read with -b -1 only on servers that store the journal on disk (/var/log/journal).

4️⃣ journalctl error logs and kernel logs

-p selects lines by log priority. Giving one level shows that level and all levels more important than it, and you can write the level either as a name or as a number.

LevelNumericMeaning
emerg0The system is unusable
alert1Action must be taken immediately
crit2Critical error
err3Error
warning4Warning
notice5Normal but worth noting; the level of lines written by logger without -p
info6Info
debug7Debug message

After writing one err-level line with logger and selecting with -p err, the notice-level line with the same tag (journalctl test message) dropped out and only the err line remained.

logger -t myapp -p user.err 'journalctl error test'; journalctl -q -t myapp -p err
Oct 28 07:12:46 server2 myapp[347704]: journalctl error test

Joining two levels with two dots prints only that range. Selecting warning..err leaves only warning and error levels.

journalctl -q -t myapp -p warning..err
Oct 28 07:12:46 server2 myapp[347704]: journalctl error test

-k keeps only kernel messages and prints only lines since the current boot.

journalctl -k -n 3
Oct 26 10:14:25 server1 systemd-rc-local-generator[96245]: /etc/rc.d/rc.local is not marked executable, skipping.
Oct 27 10:47:57 server1 systemd-rc-local-generator[512078]: /etc/rc.d/rc.local is not marked executable, skipping.
Oct 27 11:01:10 server1 systemd-rc-local-generator[520023]: /etc/rc.d/rc.local is not marked executable, skipping.

The last three -k lines on the AlmaLinux server were all systemd-rc-local-generator lines. These lines are messages written to the kernel log buffer, so they are stored with _TRANSPORT set to kernel and also appear with -k.

5️⃣ journalctl output formats

-o changes the format of each line. The default short is almost the same as a syslog file, and short-iso changes the time to ISO 8601 format including the time zone. Switching to short-iso on the AlmaLinux server added +0000 to the end of the time.

journalctl -u crond -n 2 -o short-iso
2026-10-28T07:01:01+0000 server1 run-parts[841394]: (/etc/cron.hourly) starting 0anacron
2026-10-28T07:01:01+0000 server1 CROND[841384]: (root) CMDEND (run-parts /etc/cron.hourly)

cat removes the time and the host name and prints only the message, so use it when passing messages to grep or another program.

journalctl -u crond -n 2 -o cat
(/etc/cron.hourly) starting 0anacron
(root) CMDEND (run-parts /etc/cron.hourly)

json and json-pretty print the fields stored in the journal as names and values. When you choose fields with --output-fields, the cursor, time and boot ID fields always come along. Even when only four fields were chosen on the Debian 12 server, __CURSOR, _BOOT_ID and two time fields appeared with them.

journalctl -q -t myapp -n 1 -o json-pretty --output-fields=MESSAGE,PRIORITY,SYSLOG_IDENTIFIER,_PID
{
	"__REALTIME_TIMESTAMP" : "1793171676664200",
	"_PID" : "347877",
	"SYSLOG_IDENTIFIER" : "myapp",
	"MESSAGE" : "follow line 2",
	"__CURSOR" : "s=2a6f0c1d9e8b47a3b5c4d3e2f1a0b9c8;i=1a2b3;b=b7e3d1a04c9f4e2a8d6c5b1f0e2a9c47;m=17cf8fe36f5;t=65ee150cf1188;x=1f2e3d4c5b6a7980",
	"_BOOT_ID" : "b7e3d1a04c9f4e2a8d6c5b1f0e2a9c47",
	"PRIORITY" : "5",
	"__MONOTONIC_TIMESTAMP" : "1636264982261"
}

6️⃣ Journal storage location and cleaning up its size

Whether the journal lives in memory or on disk is decided by the Storage= value in journald.conf. The default auto stores it on disk if the /var/log/journal folder exists and in memory (/run/log/journal) if it does not.

🖥️ What writes logsServices, kernel, logger
systemd-journaldStores received logs in journal files
/run/log/journalStorage=auto (no folder), memory, cleared on reboot
/var/log/journalStorage=persistent or auto (folder exists), disk, kept after reboot
🖥️ journalctlReads and prints the journal files in both folders

The AlmaLinux server had no /var/log/journal folder, so its journal was only in /run/log/journal.

ls -ld /var/log/journal /run/log/journal
ls: cannot access '/var/log/journal': No such file or directory
drwxr-sr-x+ 4 root systemd-journal 80 Oct 17 08:30 /run/log/journal

The Debian 12 server had both folders, and its journal was building up on disk.

ls -ld /var/log/journal /run/log/journal
drwxr-sr-x+ 2 root systemd-journal   40 Oct  9 08:43 /run/log/journal
drwxr-sr-x+ 4 root systemd-journal 4096 Sep 24 12:52 /var/log/journal

To keep logs after a reboot, change Storage= in journald.conf to persistent and restart systemd-journald. According to the official manual, the /var/log/journal folder is created automatically when needed. The settings were not changed for this article.

A journal kept on disk works like an aircraft black box that you pull out and read after an incident.

--disk-usage prints the combined size of archived journal files and the files currently in use. On a regular account of the Debian 12 server, with the [Hint] notice at the top hidden by -q, the result was a single line: 6.6M.

journalctl -q --disk-usage
Archived and active journals take up 6.6M in the file system.

The maximum size of a journal stored on disk is set with SystemMaxUse=. If no value is given, the limit is 10% of the file system size (up to 4G), and the journald.conf on the Debian 12 server had 50M written in it.

grep -v '^#' /etc/systemd/journald.conf | grep -v '^$'
[Journal]
SystemMaxUse=50M

To shrink old journals right away, set the size to keep with --vacuum-size or the period to keep with --vacuum-time. Both commands delete journal files, so they were not run for this article.

journalctl --vacuum-size=200M

--vacuum-size=200M deletes archived journal files starting with the oldest until the total size is below 200M.

journalctl --vacuum-time=2weeks

--vacuum-time=2weeks deletes archive files that contain only lines older than 2 weeks.

vacuum deletes only archived files and leaves the files currently in use, so even after running it the --disk-usage number may not drop to the size you set.

Text logs under /var/log are written by rsyslog, which works separately from journald. That is why the two logs are read and sized differently.

Itemjournald(journalctl)rsyslog
How to readjournalctlcat, less, grep
Stored in/run/log/journal or /var/log/journal/var/log/messages (RHEL family) or /var/log/syslog (Debian family)
Size managementSystemMaxUse and others in journald.conflogrotate

7️⃣ journalctl read permissions and options

  • ↪️ When a regular account cannot see logs

🔲 Read permissions

Running journalctl as an account other than root shows a [Hint] message at the top, and only the logs that account wrote are visible. Searching for nginx logs as a regular account on the Debian 12 server printed only [-- No entries --] after the notice.

journalctl -u nginx -n 5
Hint: You are currently not seeing messages from other users and the system.
      Users in groups 'adm', 'systemd-journal' can see all messages.
      Pass -q to turn off this notice.
-- No entries --

According to id -nG, this account belonged to only one group, and it was not in the adm or systemd-journal groups the notice mentions.

id -nG
user

The official manual explains that accounts in the systemd-journal, adm and wheel groups can read the whole journal. adm and wheel come with other permissions set by the distribution, and wheel often allows administrative work as well, so the systemd-journal group is the right fit for an account that only reads logs.

usermod -aG systemd-journal user

The usermod command that adds the group was not run for this article. After adding the group, log in again and check the groups with id -nG. An account with administrator rights also sees all logs when it runs sudo journalctl.

The [Hint] message is hidden with -q. Even with -q, though, the visible logs are only the lines that account wrote. --user reads that account's user journal and works only on servers that store the journal on disk. On the Debian 12 server, which keeps its journal on disk, that account's systemd lines and logger lines appeared.

journalctl --user -n 3
Oct 28 07:12:35 server2 systemd[347665]: Reached target default.target - Main User Target.
Oct 28 07:12:35 server2 systemd[347665]: Startup finished in 181ms.
Oct 28 07:12:44 server2 myapp[347693]: journalctl test message

🔲 journalctl command options

📌 Main options: results from this article

OptionTaskResult in this article
-n linesPrint only the last few lines; 10 lines if the number is left out-n 3 shows the last three lines
-rReverse the order, newest line at the topIn the crond log, the CMDEND line written last is at the top
-fKeep printing new lines after the last lineThe two lines written with logger follow right below
-qHide notices such as [Hint]The --disk-usage result of a regular Debian 12 account is a single line: 6.6M
-u unitPrint only that service's logWith -u written twice, four crond lines are followed by two nginx reload lines in time order
-t tagPrint only logs with the tag given to logger -t-t myapp shows the lines written with logger
-g textPrint only lines whose message contains that textOf the last two crond lines, only the one containing anacron remains
--since, --untilStart and end of the time range to print--since '-2h' starts at the crond lines written at 06:01
-bOnly logs since the current boot; -b -1 is the previous bootOn the AlmaLinux server, which does not keep its journal on disk, -b -1 only shows the [no persistent journal was found] notice
--list-bootsList of boots kept in the journalThe AlmaLinux server has only one boot record
-p levelPrint only that priority and more important levels-p err drops the notice line and keeps only the err line; warning..err gives the same single line
-kPrint only kernel messages from the current bootThe last three lines are all systemd-rc-local-generator lines
-o formatChange the output format of each lineshort-iso adds +0000 to the end of the time; cat leaves only the message
--output-fields fieldsChoose fields in json outputEven with only four fields chosen, __CURSOR, _BOOT_ID and two time fields come along
--disk-usagePrint the total size taken by journal files6.6M on a regular account of the Debian 12 server
--userRead that account's user journalOn the Debian 12 server, that account's systemd lines and logger lines appear
--utcPrint times in UTCEven on the AlmaLinux server with its own time zone, the crond log times switch to UTC
field=valuePrint only lines with that field value_PID=347704 shows only the one err line written by logger

📎 Other options: per the official manual

OptionTask
--no-pagerPrint straight to the terminal without going through less
-e, --pager-endOpen less at the end of the journal; 1000 lines unless -n is given
-x, --catalogAdd explanation text from the message catalog to log lines
-a, --allPrint fields in full, even with unprintable characters or very long values
-N, --fieldsPrint all field names used in the journal
-F, --field= fieldPrint all values that field has
-D folderRead the journal in the given folder instead of the default location
--file= fileRead the given journal file; can be given more than once
--vacuum-size= sizeDelete archived journal files, oldest first, until below the given size
--vacuum-time= periodDelete archive files that contain only lines older than the given period
--vacuum-files= countDelete archived journal files, keeping only the given number
--rotateArchive the journal files in use and start new ones
--flushMove the journal from memory (/run/log/journal) to disk (/var/log/journal) when storage is persistent

🔲 journalctl command simulator

In the simulator below, you can type commands yourself to check recent logs, logs by service, time ranges, priorities and output formats.

journalctl command simulatorsystemd 252
[root@server work]#
It runs only in your browser; lines written with logger disappear when you reload, and ↑↓ bring back commands you typed before.

🔢 FAQ & Recommended Content

Adding --utc prints times in UTC regardless of the server's time zone setting. Even on the AlmaLinux server with its own time zone, the crond log with --utc showed times in UTC.

Writing a field name and value joined by an equals sign, as in journalctl _PID=347704, keeps only lines with that value. Searching with the process number of the err line written by logger returned only that line, and writing it together with -u prints only lines that meet both conditions.

🧭 System info · settings commands: recommended content 8 posts · 2 references
🗂️ System info · settings commands
📄 CPU · RAM · disk · OS info 📄 uname · kernel version 📄 free command 📄 uptime command
📄 timedatectl command 📄 localectl command
📄 logrotate 📄 journalctl command

ℹ️ Affiliate Disclosure
This site's content contains affiliate links. When a visitor buys a product or service through one of them, the site receives a commission from the seller. The amount the buyer pays(it goes down during event discounts ↓)does not go up. Posted prices, discounts, and stock reflect the time of writing and may differ, so confirm with the seller before buying. Products are chosen and reviewed by our own standards, and commissions do not affect the order or content of reviews.

Leave a Reply

Your email address will not be published. Required fields are marked *

Prove your humanity: 7   +   2   =