>
>
>
>
When working with systemd journals, it's crucial to understand that the process name (like "echo") appearing in log entries is fundamentally different from the syslog identifier used by journalctl's filtering mechanisms.
>
>
# Process name appears in default logging:
>
>$ systemd-cat echo "test"
>
>$ journalctl -b | grep "echo"
>
>Jul 25 13:52:26 mycomputer echo[25098]: test
>
># Explicit identifier shows different behavior:
>
>$ systemd-cat -t myapp echo "test"
>
>$ journalctl -b -t myapp
>
>Jul 25 13:56:08 mycomputer myapp[25213]: test
>
>
>
>
The -t/--identifier
and -u/--unit
filters in journalctl specifically match against:
>
>
-
>
- Syslog identifiers (set via -t)
>
> - Systemd unit names (for -u)
>
>
>
>
>
Process names are recorded as part of the message content, not as filterable metadata. This explains why journalctl -t echo
returns no results when only the process name is "echo".
>
>
>
>
Here are three reliable ways to filter by process name:
>
>
1. Using _COMM Field Matching
>
>
# Filter by exact process name:
>
>journalctl _COMM=echo
>
># Case-sensitive regex matching:
>
>journalctl _COMM=~'.*httpd.*'
>
>
2. Combining With Other Fields
>
>
# Process name plus priority:
>
>journalctl _COMM=nginx PRIORITY=4
>
># Time-constrained process filtering:
>
>journalctl _COMM=postgres --since "1 hour ago"
>
>
3. Advanced JSON Output Processing
>
>
# Extract process-specific logs to JSON:
>
>journalctl -o json | jq 'select(._COMM == "python3")'
>
># Real-time monitoring of a process:
>
>journalctl -f -o json | jq 'select(._COMM == "node")'
>
>
>
>
For services you control, consider these approaches:
>
>
# Systemd service unit with explicit identifier:
>
>[Service]
>
>SyslogIdentifier=myapp-process
>
>ExecStart=/usr/bin/myapp
>
>
Or configure logging in your application:
>
>
# Python example using systemd.journal
>
>from systemd import journal
>
>journal.send('Message', SYSLOG_IDENTIFIER='myapp')
>
>
>
>
Field-based filtering (_COMM
) is generally faster than text searches because:
>
>
-
>
- Journal indexes metadata fields
>
> - No full message scanning required
>
> - Works efficiently with large log volumes
>
>
>
>
>
# Benchmark comparison (time commands):
>
>time journalctl _COMM=sshd | wc -l
>
>time journalctl | grep sshd | wc -l
>
>
When working with systemd journals, many developers encounter a common challenge: filtering logs by the original process name when it's not explicitly set as an identifier. The default behavior shows the process name in square brackets (e.g., echo[25098]
), but standard filtering methods don't work as expected.
# This won't work
journalctl -f -t echo
journalctl -f -u echo
The -t
flag filters by syslog identifier, while -u
filters by unit name. Neither matches against the process name shown in brackets.
Solution 1: Using _COMM Field Filtering
The most direct approach uses journalctl's field filtering capability:
# Filter by process name (case sensitive)
journalctl _COMM=echo
# Case insensitive version
journalctl _COMM=echo -i
Solution 2: Combining With Other Filters
# Show recent entries for specific process
journalctl _COMM=nginx --since "1 hour ago"
# Follow logs in real-time
journalctl _COMM=postgres -f
Solution 3: JSON Output for Processing
# Get structured output for script processing
journalctl _COMM=sshd -o json
For processes you control, explicitly setting identifiers makes filtering more reliable:
# Using systemd-cat with custom identifier
systemd-cat -t myapp /path/to/script.sh
# Then filter normally
journalctl -t myapp
Multiple Process Filtering
# Show logs for multiple processes
journalctl _COMM=nginx OR _COMM=php-fpm
Priority-Based Filtering
# Show errors from specific process
journalctl _COMM=apache2 PRIORITY=3
Persistent Filtering
Create persistent filters using journald configuration:
# /etc/systemd/journald.conf
Storage=persistent
- Use
journalctl --fields
to see all available fields - Check process names with
ps aux
when unsure - Remember that _COMM matches the executable name, not the full path