journalctl — Query the systemd journal — kernel and service logs across all 5 shells
Equivalents in every shell
journalctl -u nginx -fFollow (`-f`) the nginx unit's journal — equivalent to `tail -f /var/log/nginx/access.log` but covers ALL streams the unit writes (stdout, stderr, sd_journal_send) and survives rotation. `-u <unit>` filter by unit, `-p <priority>` by syslog priority (err / warning / etc), `-S "1h ago"` / `-U "2h ago"` time window, `-b` current boot, `-b -1` previous boot, `--since today`, `-k` kernel ring buffer only. `-o json` for machine-parseable output.
journalctl -u nginx -fSame systemd binary on Linux. NOT available on macOS — macOS uses `unified logging` via `log show` / `log stream` (Apple's own structured logging system, similar concept, different syntax). macOS rough equivalent: `log show --predicate 'subsystem == "com.example.nginx"' --last 1h` / `log stream --predicate 'process == "nginx"'` for the follow-mode.
journalctl -u nginx -fSame external. Fish-friendly composition: `journalctl --since "1 hour ago" -u nginx | string match -r "error|fatal"` filters errors out of a one-hour window. Note that journal output is colour-coded by default when stdout is a tty, but piped output goes plain — pass `--no-pager` to bypass less, or `-o cat` to drop the timestamp / unit prefix entirely.
Get-WinEvent -LogName System -MaxEvents 50Windows Event Log is the conceptual equivalent of systemd journal — same model (binary, indexed, structured). `Get-WinEvent -LogName System` reads the System log, `Application` reads app logs, `Security` (requires elevation) reads audit events. Filter via `-FilterHashtable @{LogName="System"; Level=2; StartTime=(Get-Date).AddHours(-1)}` (Level 2 = Error). Stream-mode (follow) is awkward in pwsh — use `Wait-Event` or poll `Get-WinEvent` with a sliding `StartTime`. The older `Get-EventLog` cmdlet is deprecated; use `Get-WinEvent` for new code.
wevtutil qe System /c:50 /f:text /rd:true`wevtutil` is the Windows builtin command-line wrapper around the Event Log. `qe <log>` query events; `/c:N` limit count; `/f:text` plain-text format (default is XML); `/rd:true` reverse direction (newest first). Filter by XPath: `/q:"*[System[Level=2]]"` (errors only). Much more verbose than `journalctl` — pwsh `Get-WinEvent` is the cleaner answer.
Worked examples
Follow a service's logs in real time
journalctl -u nginx -fjournalctl -u nginx -fGet-WinEvent -LogName Application | Where-Object ProviderName -eq nginxwevtutil qe Application /q:"*[System[Provider[@Name='nginx']]]"Show kernel messages from the current boot
journalctl -k -bjournalctl -k -bGet-WinEvent -LogName System -ProviderName "Microsoft-Windows-Kernel-General"wevtutil qe System /q:"*[System[Provider[@Name='Microsoft-Windows-Kernel-General']]]"Errors only, since one hour ago
journalctl --since "1 hour ago" -p errjournalctl --since "1 hour ago" -p errGet-WinEvent -FilterHashtable @{LogName="System"; Level=2; StartTime=(Get-Date).AddHours(-1)}wevtutil qe System /q:"*[System[Level=2 and TimeCreated[timediff(@SystemTime) <= 3600000]]]"Gotchas
- Journal storage is `/var/run/log/journal/<machine-id>/` (volatile, lost on reboot) by default on most distros — `journalctl` then ONLY shows the CURRENT BOOT. To persist across reboots, `mkdir -p /var/log/journal && systemctl restart systemd-journald` (the existence of `/var/log/journal/` flips the daemon to persistent mode). Without this, `journalctl -b -1` (previous boot) returns nothing.
- A unit may have NO output in `journalctl -u foo` even when it's clearly running — happens when the service was started before journald, or it writes to syslog only, or its `StandardOutput=` is set to `null` / `file:` instead of the default `journal`. Check `systemctl cat foo` to see the unit's output configuration.
- Time filters are TIMEZONE-sensitive. `journalctl --since "2024-01-15 03:00"` interprets the timestamp in your CURRENT shell's timezone. If your server runs UTC but your shell is in CET, the result is offset by an hour. Be explicit: `--since "2024-01-15 03:00 UTC"` for cross-timezone debugging.
- Windows Event Log priorities are: 1=Critical, 2=Error, 3=Warning, 4=Information, 5=Verbose. These don't match syslog (which is 0=emerg up to 7=debug). When translating from Linux experience, double-check: `journalctl -p err` (syslog "err" = priority 3) corresponds to `Level=2` in Windows. The naming is backwards-ish.
- `journalctl` follow-mode (`-f`) shows new lines as they arrive AT THE JOURNAL, not as the program writes them. A service that buffers stdout for performance (some Python web frameworks) emits to journal only when its buffer flushes — which can lag by minutes. Workaround: run the service with `PYTHONUNBUFFERED=1` or equivalent so writes are immediate.