{"id":116857,"date":"2026-03-25T18:10:59","date_gmt":"2026-03-25T15:10:59","guid":{"rendered":"https:\/\/computingforgeeks.com\/?p=116857"},"modified":"2026-03-25T18:11:00","modified_gmt":"2026-03-25T15:11:00","slug":"journalctl-filter-systemd-logs-linux","status":"publish","type":"post","link":"https:\/\/computingforgeeks.com\/journalctl-filter-systemd-logs-linux\/","title":{"rendered":"Filter Systemd Logs with journalctl (Practical Examples)"},"content":{"rendered":"\n<p>When something breaks at 3 AM, journalctl is the first command you reach for. It queries the systemd journal and lets you filter by service, time, priority, PID, or any combination of these. The structured binary format means you can slice logs in ways that plain text files and <code>grep<\/code> simply cannot match.<\/p>\n\n\n\n<p>This guide covers every practical journalctl filter you will use in day-to-day troubleshooting and monitoring. Each example was tested on a live Ubuntu 24.04 system with systemd 255. For setting up persistent journal storage and retention limits, see our <a href=\"https:\/\/computingforgeeks.com\/persistent-systemd-journal-linux\/\" target=\"_blank\" rel=\"noreferrer noopener\">persistent systemd journal configuration guide<\/a>.<\/p>\n\n\n\n<p><em>Tested <strong>March 2026<\/strong> on Ubuntu 24.04 LTS with systemd 255 (255.4-1ubuntu8.1)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">View Recent Log Entries<\/h2>\n\n\n\n<p>Show the last N log entries with <code>-n<\/code>. This is your go-to for a quick look at what just happened:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -n 10 --no-pager<\/code><\/pre>\n\n\n\n<p>The output shows the most recent 10 entries with timestamp, hostname, process, and message:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Mar 25 15:07:20 ubuntu systemd[1016]: Reached target basic.target - Basic System.\nMar 25 15:07:20 ubuntu systemd[1016]: Reached target default.target - Main User Target.\nMar 25 15:07:20 ubuntu systemd[1016]: Startup finished in 141ms.\nMar 25 15:07:20 ubuntu systemd[1]: Started user@1000.service - User Manager for UID 1000.\nMar 25 15:07:20 ubuntu systemd[1]: Started session-1.scope - Session 1 of User ubuntu.<\/code><\/pre>\n\n\n\n<p>Show entries in reverse order (newest first) with <code>-r<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -r -n 5 --no-pager<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Follow Logs in Real Time<\/h2>\n\n\n\n<p>Watch new log entries as they appear, similar to <code>tail -f<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -f<\/code><\/pre>\n\n\n\n<p>Combine with a service filter to watch only one service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -fu ssh.service<\/code><\/pre>\n\n\n\n<p>Press <code>Ctrl+C<\/code> to stop following.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Filter by Service Unit<\/h2>\n\n\n\n<p>The <code>-u<\/code> flag filters logs for a specific systemd service. This is the most common filter for troubleshooting:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -u ssh.service --no-pager -n 8<\/code><\/pre>\n\n\n\n<p>The output shows only SSH-related messages:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Mar 25 15:07:18 ubuntu sshd[1009]: Server listening on :: port 22.\nMar 25 15:07:18 ubuntu systemd[1]: Started ssh.service - OpenBSD Secure Shell server.\nMar 25 15:07:18 ubuntu sshd[1010]: Connection closed by 129.222.187.73 port 32744\nMar 25 15:07:20 ubuntu sshd[1011]: Accepted publickey for ubuntu from 129.222.187.73 port 51497 ssh2\nMar 25 15:07:20 ubuntu sshd[1011]: pam_unix(sshd:session): session opened for user ubuntu(uid=1000)<\/code><\/pre>\n\n\n\n<p>Filter multiple services at once:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -u ssh.service -u nginx.service --no-pager -n 20<\/code><\/pre>\n\n\n\n<p>Note: service names vary between distros. Ubuntu 24.04 uses <code>ssh.service<\/code> while Rocky Linux uses <code>sshd.service<\/code>. Check your service name with <code>systemctl list-units --type=service<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Filter by Time<\/h2>\n\n\n\n<p>Narrow logs to a specific time window with <code>--since<\/code> and <code>--until<\/code>. Both accept absolute timestamps and relative expressions.<\/p>\n\n\n\n<p>Logs from the last hour:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl --since \"1 hour ago\" --no-pager -n 20<\/code><\/pre>\n\n\n\n<p>Logs from today only:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl --since today --no-pager -n 20<\/code><\/pre>\n\n\n\n<p>Logs between two specific timestamps:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl --since \"2026-03-25 15:06:00\" --until \"2026-03-25 15:07:30\" --no-pager -n 10<\/code><\/pre>\n\n\n\n<p>The output shows only entries within that 90-second window:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Mar 25 15:07:22 ubuntu sshd[1011]: pam_unix(sshd:session): session closed for user ubuntu\nMar 25 15:07:22 ubuntu systemd-logind[758]: Session 1 logged out. Waiting for processes to exit.\nMar 25 15:07:22 ubuntu systemd[1]: session-1.scope: Deactivated successfully.\nMar 25 15:07:22 ubuntu systemd[1]: session-1.scope: Consumed 1.932s CPU time.<\/code><\/pre>\n\n\n\n<p>Logs from yesterday:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl --since yesterday --until today --no-pager<\/code><\/pre>\n\n\n\n<p>Other relative expressions that work: <code>\"5 minutes ago\"<\/code>, <code>\"2 hours ago\"<\/code>, <code>\"3 days ago\"<\/code>, <code>yesterday<\/code>, <code>today<\/code>, <code>now<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Filter by Priority Level<\/h2>\n\n\n\n<p>Syslog priority levels range from 0 (emergency) to 7 (debug). The <code>-p<\/code> flag filters by priority, showing all entries at the specified level and above:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -p err --no-pager<\/code><\/pre>\n\n\n\n<p>This shows entries at <code>err<\/code> (3) and above, including <code>crit<\/code>, <code>alert<\/code>, and <code>emerg<\/code>. Available priority names:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Level<\/th><th>Name<\/th><th>Meaning<\/th><\/tr><\/thead><tbody><tr><td>0<\/td><td><code>emerg<\/code><\/td><td>System is unusable<\/td><\/tr><tr><td>1<\/td><td><code>alert<\/code><\/td><td>Immediate action required<\/td><\/tr><tr><td>2<\/td><td><code>crit<\/code><\/td><td>Critical conditions<\/td><\/tr><tr><td>3<\/td><td><code>err<\/code><\/td><td>Error conditions<\/td><\/tr><tr><td>4<\/td><td><code>warning<\/code><\/td><td>Warning conditions<\/td><\/tr><tr><td>5<\/td><td><code>notice<\/code><\/td><td>Normal but significant<\/td><\/tr><tr><td>6<\/td><td><code>info<\/code><\/td><td>Informational messages<\/td><\/tr><tr><td>7<\/td><td><code>debug<\/code><\/td><td>Debug-level messages<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Filter a specific priority range (e.g., only warnings):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -p warning..warning --no-pager -n 10<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Filter by Boot<\/h2>\n\n\n\n<p>With persistent journal storage, you can query logs from previous boots. List all recorded boots:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl --list-boots<\/code><\/pre>\n\n\n\n<p>Each boot has an index number (0 = current, -1 = previous) and a boot ID:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>IDX BOOT ID                          FIRST ENTRY                 LAST ENTRY\n  0 6bbaadfab85347a28818957bb54af405 Wed 2026-03-25 15:06:20 UTC Wed 2026-03-25 15:07:20 UTC<\/code><\/pre>\n\n\n\n<p>View logs from the current boot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -b<\/code><\/pre>\n\n\n\n<p>View logs from the previous boot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -b -1<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Filter by Kernel Messages<\/h2>\n\n\n\n<p>The <code>-k<\/code> flag shows only kernel messages (equivalent to <code>dmesg<\/code> but with timestamps and filtering):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -k --no-pager -n 5<\/code><\/pre>\n\n\n\n<p>Kernel messages include hardware detection, driver loading, and filesystem events:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Mar 25 15:06:44 ubuntu kernel: kauditd_printk_skb: 103 callbacks suppressed\nMar 25 15:06:44 ubuntu kernel: loop0: detected capacity change from 0 to 8\nMar 25 15:06:44 ubuntu kernel: audit: type=1400 audit(1774451204.577:115): apparmor=\"STATUS\" operation=\"profile_replace\"<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Filter by PID, UID, or GID<\/h2>\n\n\n\n<p>Filter logs from a specific process ID:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl _PID=1009 --no-pager -n 5<\/code><\/pre>\n\n\n\n<p>Filter by user ID (all messages from root):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl _UID=0 --no-pager -n 5<\/code><\/pre>\n\n\n\n<p>Find the PID of a running service first, then query its logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SSHD_PID=$(pgrep -o sshd)\njournalctl _PID=$SSHD_PID --no-pager<\/code><\/pre>\n\n\n\n<p>Filter by executable path (all messages from the sshd binary):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl _EXE=\/usr\/sbin\/sshd --no-pager -n 5<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Search with Pattern Matching<\/h2>\n\n\n\n<p>The <code>-g<\/code> flag (or <code>--grep<\/code>) searches message text using regular expressions. Find all SSH-related entries:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -g \"ssh\" --no-pager -n 5<\/code><\/pre>\n\n\n\n<p>Search for failed login attempts:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -g \"Failed password|authentication failure\" --no-pager<\/code><\/pre>\n\n\n\n<p>Case-insensitive search with <code>--case-sensitive=no<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -g \"error\" --case-sensitive=no --no-pager -n 10<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Output Formats<\/h2>\n\n\n\n<p>Journalctl supports multiple output formats via <code>-o<\/code>. The format you choose depends on whether you are reading logs manually or feeding them to a script.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Format<\/th><th>Flag<\/th><th>Use Case<\/th><\/tr><\/thead><tbody><tr><td>Default (short)<\/td><td><code>-o short<\/code><\/td><td>Human-readable, syslog style<\/td><\/tr><tr><td>ISO timestamps<\/td><td><code>-o short-iso<\/code><\/td><td>Unambiguous timestamps for log analysis<\/td><\/tr><tr><td>JSON (compact)<\/td><td><code>-o json<\/code><\/td><td>Piping to <code>jq<\/code> or scripts<\/td><\/tr><tr><td>JSON (pretty)<\/td><td><code>-o json-pretty<\/code><\/td><td>Readable structured data<\/td><\/tr><tr><td>Verbose<\/td><td><code>-o verbose<\/code><\/td><td>All metadata fields for debugging<\/td><\/tr><tr><td>Message only<\/td><td><code>-o cat<\/code><\/td><td>Just the message text, no metadata<\/td><\/tr><tr><td>Export<\/td><td><code>-o export<\/code><\/td><td>Binary export for <code>systemd-journal-remote<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>ISO timestamp format for clean log analysis:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -o short-iso -n 3 --no-pager<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>2026-03-25T15:07:20+00:00 ubuntu systemd[1016]: Startup finished in 141ms.\n2026-03-25T15:07:20+00:00 ubuntu systemd[1]: Started user@1000.service - User Manager for UID 1000.\n2026-03-25T15:07:20+00:00 ubuntu systemd[1]: Started session-1.scope - Session 1 of User ubuntu.<\/code><\/pre>\n\n\n\n<p>JSON output with full structured metadata (useful for piping to <code>jq<\/code>):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -u ssh.service -n 1 -o json-pretty --no-pager<\/code><\/pre>\n\n\n\n<p>The JSON output includes every field the journal stores for that entry:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n    \"PRIORITY\" : \"6\",\n    \"_UID\" : \"0\",\n    \"_SYSTEMD_UNIT\" : \"ssh.service\",\n    \"_EXE\" : \"\/usr\/sbin\/sshd\",\n    \"_PID\" : \"1218\",\n    \"MESSAGE\" : \"pam_unix(sshd:session): session opened for user ubuntu(uid=1000)\",\n    \"__REALTIME_TIMESTAMP\" : \"1774451258043395\",\n    \"_HOSTNAME\" : \"test-ubuntu-24-computingforgeeks-com\"\n}<\/code><\/pre>\n\n\n\n<p>Verbose format shows all metadata fields for a single entry:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -u ssh.service -n 1 -o verbose --no-pager<\/code><\/pre>\n\n\n\n<p>This is the most detailed view available. Each field (PID, UID, executable path, cgroup, boot ID) appears on its own line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Wed 2026-03-25 15:07:38.042876 UTC\n    _BOOT_ID=6bbaadfab85347a28818957bb54af405\n    _MACHINE_ID=c062bd9deb7c533216c9fa60191f76f3\n    PRIORITY=6\n    _UID=0\n    _SYSTEMD_UNIT=ssh.service\n    _EXE=\/usr\/sbin\/sshd\n    _PID=1218\n    _CMDLINE=\"sshd: ubuntu [priv]\"\n    MESSAGE=pam_unix(sshd:session): session opened for user ubuntu(uid=1000)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Combine Filters<\/h2>\n\n\n\n<p>The real power of journalctl comes from combining filters. Each filter narrows the results further.<\/p>\n\n\n\n<p>SSH errors in the last hour:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -u ssh.service -p err --since \"1 hour ago\" --no-pager<\/code><\/pre>\n\n\n\n<p>Kernel messages from the previous boot at warning level or above:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -k -b -1 -p warning --no-pager<\/code><\/pre>\n\n\n\n<p>All root user activity from yesterday, in JSON format:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl _UID=0 --since yesterday --until today -o json --no-pager<\/code><\/pre>\n\n\n\n<p>Follow nginx logs at error priority only:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -fu nginx.service -p err<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Disk Usage and Cleanup<\/h2>\n\n\n\n<p>Check how much disk space the journal uses:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl --disk-usage<\/code><\/pre>\n\n\n\n<p>On a fresh system, this is typically small:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Archived and active journals take up 16.0M in the file system.<\/code><\/pre>\n\n\n\n<p>Remove journal entries older than 30 days:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo journalctl --vacuum-time=30d<\/code><\/pre>\n\n\n\n<p>Shrink the journal to a maximum size:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo journalctl --vacuum-size=500M<\/code><\/pre>\n\n\n\n<p>For permanent size and retention limits, configure <code>\/etc\/systemd\/journald.conf<\/code> as described in our <a href=\"https:\/\/computingforgeeks.com\/persistent-systemd-journal-linux\/\" target=\"_blank\" rel=\"noreferrer noopener\">persistent journal storage guide<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Quick Reference<\/h2>\n\n\n\n<p>All the filtering commands in one table:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Command<\/th><th>What It Shows<\/th><\/tr><\/thead><tbody><tr><td><code>journalctl -n 20<\/code><\/td><td>Last 20 entries<\/td><\/tr><tr><td><code>journalctl -r<\/code><\/td><td>Reverse order (newest first)<\/td><\/tr><tr><td><code>journalctl -f<\/code><\/td><td>Follow in real time<\/td><\/tr><tr><td><code>journalctl -u ssh.service<\/code><\/td><td>Entries for a service<\/td><\/tr><tr><td><code>journalctl -p err<\/code><\/td><td>Errors and above<\/td><\/tr><tr><td><code>journalctl -k<\/code><\/td><td>Kernel messages<\/td><\/tr><tr><td><code>journalctl -b<\/code><\/td><td>Current boot only<\/td><\/tr><tr><td><code>journalctl -b -1<\/code><\/td><td>Previous boot<\/td><\/tr><tr><td><code>journalctl --since \"1 hour ago\"<\/code><\/td><td>Last hour<\/td><\/tr><tr><td><code>journalctl --since today<\/code><\/td><td>Today only<\/td><\/tr><tr><td><code>journalctl _PID=1234<\/code><\/td><td>Specific process<\/td><\/tr><tr><td><code>journalctl _UID=0<\/code><\/td><td>All root activity<\/td><\/tr><tr><td><code>journalctl -g \"pattern\"<\/code><\/td><td>Grep messages<\/td><\/tr><tr><td><code>journalctl -o json-pretty<\/code><\/td><td>JSON output<\/td><\/tr><tr><td><code>journalctl -o short-iso<\/code><\/td><td>ISO timestamps<\/td><\/tr><tr><td><code>journalctl -o verbose<\/code><\/td><td>All metadata fields<\/td><\/tr><tr><td><code>journalctl --disk-usage<\/code><\/td><td>Journal disk usage<\/td><\/tr><tr><td><code>journalctl --vacuum-time=30d<\/code><\/td><td>Delete entries older than 30 days<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>For managing <a href=\"https:\/\/computingforgeeks.com\/systemd-timers-linux\/\" target=\"_blank\" rel=\"noreferrer noopener\">scheduled tasks with systemd timers<\/a> or <a href=\"https:\/\/computingforgeeks.com\/systemctl-commands-linux\/\" target=\"_blank\" rel=\"noreferrer noopener\">controlling services with systemctl<\/a>, check our other systemd guides.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>When something breaks at 3 AM, journalctl is the first command you reach for. It queries the systemd journal and lets you filter by service, time, priority, PID, or any combination of these. The structured binary format means you can slice logs in ways that plain text files and grep simply cannot match. This guide &#8230; <a title=\"Filter Systemd Logs with journalctl (Practical Examples)\" class=\"read-more\" href=\"https:\/\/computingforgeeks.com\/journalctl-filter-systemd-logs-linux\/\" aria-label=\"Read more about Filter Systemd Logs with journalctl (Practical Examples)\">Read more<\/a><\/p>\n","protected":false},"author":21,"featured_media":164540,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[299,50],"tags":[2667,205,37418,37419],"class_list":["post-116857","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to","category-linux-tutorials","tag-logging","tag-security","tag-systemd-logs","tag-using-journalctl"],"_links":{"self":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/116857","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/comments?post=116857"}],"version-history":[{"count":3,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/116857\/revisions"}],"predecessor-version":[{"id":164539,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/116857\/revisions\/164539"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/media\/164540"}],"wp:attachment":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/media?parent=116857"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/categories?post=116857"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/tags?post=116857"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}