Any user can read their own logs; reading the full system journal needs or membership in the or group. Filters combine, so is one valid command.
Service Logs
| Command | What it does |
|---|---|
| Every log line from the nginx unit, oldest first | |
| Open the pager at the end, newest lines on screen | |
| Two units interleaved in time order (repeat for more) | |
| Units matching a pattern | |
| Jump to the end with catalog explanations, what tells you to run after a failure | |
| A user service, no sudo needed | |
| Follow kubelet on a Kubernetes node, the first stop when a node goes NotReady | |
| The whole journal, every unit and the kernel |
shows nothing for a misspelled unit name rather than erroring; confirm the name with from the systemctl cheat sheet.
Follow and Tail
| Command | What it does |
|---|---|
| Follow live, like (Ctrl+C stops) | |
| Last 100 lines ( alone means 10) | |
| Same, straight to the terminal for copy-paste | |
| Follow but start empty, only new lines | |
| Newest first | |
| Follow everything, all units at once |
Time Ranges
and take human phrases and absolute stamps, and stack with every other filter.
| Command | What it does |
|---|---|
| The last hour | |
| Since midnight ( covers all of yesterday) | |
| Since midnight at the start of that date | |
| A precise window | |
| The last 30 minutes, shorthand | |
| Exclude the most recent lines | |
| Interpret and print times in UTC instead of local |
Boots
Crash forensics live here: limits output to one boot, counted backwards from the current one.
| Command | What it does |
|---|---|
| Only the current boot | |
| The previous boot, the one that crashed or was rebooted away | |
| Every boot the journal knows, with index and time span | |
| End of the previous boot, the last thing logged before it went down | |
| Everything at error level or worse from the previous boot | |
| Kernel messages from the previous boot (OOM kills, panics, disk errors) |
After an unexplained reboot, this sequence usually finds the cause:
journalctl --list-boots
journalctl -b -1 -e
journalctl -b -1 -p err -o short-iso
journalctl -b -1 -k -g "oom|panic|error"If shows only one boot, the journal is volatile and pre-reboot logs are gone; see the persistence setup under Disk Usage below.
Priority
| Command | What it does |
|---|---|
| Priority and worse | |
| One unit, and worse | |
| Only a range of levels | |
| Numbers work too (3 is ) |
| Level | Name | Typical meaning |
|---|---|---|
| 0 | System is unusable | |
| 1 | Act immediately | |
| 2 | Critical condition | |
| 3 | Error | |
| 4 | Something to look at | |
| 5 | Normal but notable | |
| 6 | Routine | |
| 7 | Debug detail |
means 0 through 3, not just 3: a priority flag always includes everything worse than the level named.
Search and Filter
| Command | What it does |
|---|---|
| Grep the messages (PCRE; case-insensitive when the pattern is all lowercase) | |
| Grep within one unit | |
| Kernel messages only, the equivalent with timestamps and history | |
| Everything logged by one process ID | |
| Everything logged by one user's processes | |
| Everything logged by one executable | |
| Same idea, matched by process name | |
| Plain grep still works when is missing (systemd older than 239) | |
| List every unit that has logged, when you cannot recall the unit name | |
| List the field names available to filter on |
Field filters like combine with , and time flags like any other filter. shows every field a journal entry carries, which is how you discover what to filter on.
Auth and Logins
The SSH unit is on Debian and Ubuntu, on RHEL and its relatives.
| Command | What it does |
|---|---|
| Failed SSH password attempts, with source IP | |
| Successful logins, with user, IP and auth method | |
| Today's probes for accounts that do not exist | |
| The whole authpriv facility, the equivalent | |
| Who ran today, and what they ran | |
| Watch fail2ban bans and unbans live | |
| Count failed attempts this boot |
A busy public host logs thousands of failed SSH attempts a day, which is noise rather than a break-in. Look for an line from an IP you do not recognise.
User Services
reads the journal of your own systemd user manager. Without it you get the system journal, where user units do not appear.
| Command | What it does |
|---|---|
| Everything your own user services logged, no sudo needed | |
| One user unit | |
| Follow a user unit live | |
| Errors from your user services this boot | |
| Another user's user unit, read as root | |
| Everything one user's processes logged today |
shows root's user journal, not yours, which is a common five-minute detour.
Output Formats
| Command | What it does |
|---|---|
| ISO 8601 timestamps, sortable and unambiguous | |
| Microsecond timestamps | |
| One JSON object per line, for and log shippers | |
| Readable JSON, one entry at a time | |
| Message text only, no timestamps or hostnames | |
| Full weekday and date, the style stamp | |
| Drop the hostname column on a single-host box | |
| Pick the fields to print | |
| Print times in UTC | |
| Append the cursor of the last entry shown | |
| Resume from a saved cursor | |
| Read the cursor from a file and update it after, for polling scripts |
Cursors give a script an exact resume point, so a cron job can process only what arrived since its last run without overlaps or gaps.
Pager and Wrapping
Output goes through , started with . The in there chops long lines at the terminal width, which is why lines look cut off.
| Command or key | What it does |
|---|---|
| Quit the pager and get the prompt back | |
| / | Jump to the end / back to the start |
| then | Search forward inside the pager, then next match |
| then Enter | Toggle line chopping on and off from inside |
| Wrap long lines instead of chopping them, for one run | |
| Print straight to the terminal, for pipes and scripts | |
| Ellipsize fields too wide for the terminal ( is the default) | |
| No colour codes, for logs you are about to paste somewhere |
Set in your shell profile to skip the pager permanently. never uses the pager, so Ctrl+C is what ends a follow.
Export to a File
The pager is skipped automatically when output is not a terminal, so a plain redirect needs no .
| Command | What it does |
|---|---|
| Plain text dump of one unit | |
| Previous boot with sortable timestamps, for a ticket | |
| JSON lines for or a log shipper | |
| Native export format, every field preserved | |
| Read specific journal files | |
| Read a journal directory from a mounted disk or rescue boot | |
| Interleave every journal found, including other users and boots | |
| Read a container or nspawn machine's journal from the host |
Disk Usage and Vacuum
| Command | What it does |
|---|---|
| Total space the journal takes on disk | |
| Delete oldest archived files until under 500 MB | |
| Delete everything older than two weeks | |
| Keep only the five newest journal files | |
| Archive the active file so vacuum can reach it | |
| Check journal files for corruption |
Vacuum only removes archived files, so first when you need space back now. To cap size permanently and keep logs across reboots, set both in :
[Journal]
Storage=persistent
SystemMaxUse=500Msudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journaldThe edge case that bites: the default persists only if already exists. Debian and Ubuntu ship the directory, so their logs survive reboots; RHEL and CentOS generally do not, so every boot starts the journal empty and has nothing to show until you create it.
Gotchas
- Empty output from usually means a misspelled or different unit name, not missing logs. settles it.
- erroring with no persistent journal means the logs you want are already gone. Set up persistence today, before the crash you will want to debug.
- shows and everything worse, and it filters on the priority the service declared. Apps that write plain text to stdout log everything at , so their errors do not surface under ; use for those.
- Timestamps print in the machine's local timezone. On servers set to UTC that is what you expect; on anything else, avoids an hour of confusion during incident timelines.
- needs systemd 239 or newer. Older hosts (CentOS 7 and friends) pipe to instead.
- There is no exclude flag. journalctl matches are positive only, so to drop one noisy unit you either name the units you do want with repeated , or pipe through .
- Searching with reads every entry, while and other field matches use the journal index. Narrow by boot or time first and the same search finishes far quicker.
- Without you see your own logs only, and journalctl says so in a hint at the top that is easy to scroll past. Add yourself to for read access without sudo.
- The journal and a service's own log files are separate worlds. nginx access logs live in , not the journal; the journal has stdout, stderr and what systemd itself says about the unit. Unit state is the same split: lists what is broken, journalctl only shows what it logged. The systemctl cheat sheet covers the service side.