journalctl in Practice - Filtering Logs from the systemd Journal
What You Can Solve with This Article
journalctl is the systemd log query tool. With the right filter combinations, you can extract specific lines from millions of log entries in seconds. The patterns below cover the majority of real-world log investigation tasks.
Most-used combinations (copy-paste ready)
# nginx errors in the last hour journalctl -u nginx -p err --since "1 hour ago" # All errors since current boot journalctl -b -p err # Follow a unit in real time journalctl -u myapp.service -f
How to filter by unit
Use -u to scope output to a specific service. This is the most-used option in practice.
# Single unit journalctl -u nginx.service # Multiple units at once journalctl -u nginx.service -u php-fpm.service
The .service suffix can be omitted — -u nginx works too.
How to specify a time range
Use --since and --until to narrow by time. Both relative and absolute formats are accepted.
# Last hour journalctl --since "1 hour ago" # Last 30 minutes journalctl --since "30 min ago" # From a specific timestamp to now journalctl --since "2026-05-30 14:00:00" # Bounded range journalctl --since "2026-05-30 10:00" --until "2026-05-30 12:00"
-S is shorthand for --since, -U for --until. The long forms are more readable in scripts.
How to show only errors
-p filters by syslog priority. Specifying a level shows that level and above (more severe).
# err and above (err, crit, alert, emerg) journalctl -p err # warning and above journalctl -p warning # Exact level only (range syntax) journalctl -p err..err
| Number | Keyword | Meaning |
|---|---|---|
| 0 | emerg | System is unusable |
| 1 | alert | Immediate action required |
| 2 | crit | Critical condition |
| 3 | err | Error |
| 4 | warning | Warning |
| 5 | notice | Normal but significant |
| 6 | info | Informational |
| 7 | debug | Debug messages |
How to follow logs in real time
-f is the equivalent of tail -f. New log entries appear as they arrive.
# Watch a unit after deploying journalctl -u myapp.service -f # Follow errors only journalctl -u myapp.service -p err -f
Press Ctrl+C to stop. Use -n to start from the last N lines.
# Start from last 50 lines, then follow journalctl -u nginx -n 50 -f
How to filter by boot
-b shows logs for the current boot only. Use --list-boots to see past boots before narrowing to a specific one.
# Current boot journalctl -b # List all past boots with their IDs journalctl --list-boots # Previous boot journalctl -b -1 # Two boots ago journalctl -b -2
-3 d7a3f8... Mon 2026-05-27 09:00 UTC—Mon 2026-05-27 18:30 UTC -2 a1b2c3... Tue 2026-05-28 08:45 UTC—Tue 2026-05-28 20:00 UTC -1 e5f6a7... Wed 2026-05-29 09:10 UTC—Wed 2026-05-29 23:45 UTC 0 b8c9d0... Thu 2026-05-30 08:00 UTC—present
How to filter by field or process
journalctl accepts direct field key-value pairs as filters. See man systemd.journal-fields for the complete list.
# By PID journalctl _PID=12345 # By command name journalctl _COMM=sshd # By syslog identifier journalctl SYSLOG_IDENTIFIER=nginx # Logs from a specific user's processes journalctl _UID=1000
journalctl -F _COMM lists all values present in the journal for the _COMM field. Useful when you are not sure which identifiers exist.
How to combine with grep
Use the built-in --grep option (v233+) or pipe to grep.
# Built-in grep journalctl -u nginx --grep "error" # Regex pattern journalctl -u nginx --grep "5[0-9][0-9]" # Pipe to grep journalctl -u nginx | grep -i "connection refused" # Combine time range and grep journalctl --since "2 hours ago" | grep "ERROR"
--grep only searches the MESSAGE field. Pipe to grep when you need to search across all fields.
How to change output format
-o controls the output format. Useful for log analysis and tool integration.
# JSON (one log entry per line) journalctl -u nginx -o json # Pretty-printed JSON journalctl -u nginx -o json-pretty # Short timestamp format journalctl -o short # Message only (no metadata) journalctl -o cat
JSON output works well with jq for further processing.
# Extract timestamp and message from errors journalctl -u nginx -p err -o json | jq -r '.__REALTIME_TIMESTAMP + " " + .MESSAGE'
Without --no-pager, journalctl opens in a pager (like less). Always add it in scripts.
journalctl -u nginx --no-pager | wc -l
Summary: Quick Reference Table
Filters can be combined freely. The standard starting point in practice is to scope by unit with -u, then narrow to errors with -p err.
| Goal | Command |
|---|---|
| Filter by unit | journalctl -u nginx |
| Time range | journalctl --since "1 hour ago" |
| Errors only | journalctl -p err |
| Current boot | journalctl -b |
| Follow | journalctl -f |
| Filter by PID | journalctl _PID=1234 |
| Combine with grep | journalctl -u nginx --grep "error" |
| JSON output | journalctl -o json |
| Disable pager | journalctl --no-pager |
# Common real-world combinations journalctl -u nginx.service -p err --since "today" --no-pager journalctl -b -p warning -u ssh.service -f