Skip to content
shellmap

journalctlQuery the systemd journal — kernel and service logs across all 5 shells

Equivalents in every shell

Bashunix
journalctl -u nginx -f

Follow (`-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.

Zshunix
journalctl -u nginx -f

Same 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.

Fishunix
journalctl -u nginx -f

Same 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.

PowerShellwindows
Get-WinEvent -LogName System -MaxEvents 50

Windows 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.

cmd.exewindows
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

Bash
journalctl -u nginx -f
Fish
journalctl -u nginx -f
PowerShell
Get-WinEvent -LogName Application | Where-Object ProviderName -eq nginx
cmd.exe
wevtutil qe Application /q:"*[System[Provider[@Name='nginx']]]"

Show kernel messages from the current boot

Bash
journalctl -k -b
Zsh
journalctl -k -b
PowerShell
Get-WinEvent -LogName System -ProviderName "Microsoft-Windows-Kernel-General"
cmd.exe
wevtutil qe System /q:"*[System[Provider[@Name='Microsoft-Windows-Kernel-General']]]"

Errors only, since one hour ago

Bash
journalctl --since "1 hour ago" -p err
Fish
journalctl --since "1 hour ago" -p err
PowerShell
Get-WinEvent -FilterHashtable @{LogName="System"; Level=2; StartTime=(Get-Date).AddHours(-1)}
cmd.exe
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.

WSL & PowerShell Core notes

pwsh`journalctl` is Linux-systemd-only. On pwsh on Linux: `& journalctl -u foo` works directly. On Windows pwsh: `Get-WinEvent` is the closest equivalent (same model). On macOS pwsh: `log show` / `log stream` (Apple's unified logging). A portable wrapper: `if ($IsLinux) { journalctl ... } elseif ($IsMacOS) { log show ... } else { Get-WinEvent ... }` — but the query syntax diverges enough that a true cross-platform layer rarely pays off.
WSLWSL2 supports `journalctl` ONLY if systemd is opted in (`[boot] systemd=true` in `/etc/wsl.conf`, then `wsl --shutdown` and relaunch). Pre-2022 WSL distros run without systemd by default and `journalctl` returns "Failed to add match: Invalid argument" or no output. Once systemd is on, all the usual `journalctl -u foo` patterns work — but remember the WSL VM shuts down ~8s after the last bash exits, so historical logs older than a few hours often won't persist unless `/var/log/journal/` is created (see persistent-storage gotcha above).

Common tasks using journalctl

Related commands