Linux系统下使用journalctl深入管理systemd日志

本文详细介绍了如何在Linux系统中使用journalctl工具来查看、过滤、监控和管理systemd Journal日志。内容涵盖了其核心功能、工作原理、按时间、服务、进程等多种方式过滤日志的方法,以及如何自定义输出格式、进行实时监控和日志清理,并提供了常见问题排查指南,是Linux系统管理员和开发者进行故障诊断与系统审计的重要参考。

阅读时长: 12 分钟
共 5605字
作者: eimoon.com

systemd Journal是现代Linux系统集中化日志管理的核心组件。它通过journald守护进程,收集来自内核 (kernel)、initrd、systemd 服务以及用户空间程序的所有日志信息,并以二进制格式进行存储。journalctl工具作为systemd Journal的配套命令行接口,提供了强大的功能,用于访问、过滤和操作这些日志数据,极大地简化了系统故障排查和日志分析的工作。

systemd Journal的核心概念与工作原理

核心要点

  • 集中式日志记录systemd Journal将内核、systemd 服务和用户应用的日志统一收集到一处,并进行索引。这种集中管理的方式,使得在系统出现问题时,管理员可以更高效地定位和分析日志。
  • 强大的过滤功能journalctl支持多种高级过滤条件,例如按启动会话 (boot session)、时间范围、systemd 单元 (unit)、进程ID (PID)、用户ID (UID)、组ID (GID) 等,极大地提升了日志检索的灵活性。
  • 灵活的基于时间查询:提供了--since--until等选项,并支持“1 hour ago”等相对时间表达式,方便用户查询特定时间段内的日志。
  • 自定义输出格式:日志可以以纯文本、JSON、JSON-pretty等多种格式显示,这使得journalctl的输出能够方便地集成到其他自动化工具或脚本中进行程序化分析。
  • 实时监控journalctl -f命令类似于tail -f,能够实时跟踪最新的日志消息,对于监控系统或服务的即时行为非常有用。
  • 持久性与临时性日志:默认情况下,systemd Journal的日志可能仅存储在内存中(临时性),系统重启后便会丢失。通过创建/var/log/journal目录并配置journald.conf,可以启用日志的持久性存储。
  • 磁盘使用与日志保留journalctl提供了--disk-usage--vacuum-size--vacuum-time等命令,帮助用户管理日志占用的磁盘空间和定义日志保留策略。
  • 故障排除利器journalctl通过聚合跨启动会话和systemd 单元的日志,显著简化了服务调试过程,有助于快速识别故障、跟踪SSH访问等安全事件。

systemd Journal的工作原理

systemd Journal的设计目标是实现所有系统日志的集中管理。journald守护进程会收集所有可用来源的数据(包括内核、各种服务、以及用户程序),并以二进制格式存储。这种存储方式带来了显著的优势:

  • 动态显示:管理员可以根据需要动态地显示日志数据。例如,可以查看几次启动前的日志,或者将两个相关服务的日志按时间顺序合并显示,从而方便地调试服务间的通信问题。
  • 任意输出格式:由于数据以结构化的二进制格式存储,journalctl可以按需输出为多种格式,例如标准的syslog格式或结构化的JSON对象,这极大地方便了与其他日志分析工具或服务的集成。
  • syslog共存或替代systemd Journal可以与现有的syslog实现(如rsyslogsyslog-ng)共存,共享日志数据,也可以完全替代传统的syslog功能,作为唯一的日志管理系统。

设置正确的系统时间 (timedatectl)

systemd Journal支持以UTC或本地时间查看日志记录。默认情况下,journalctl会显示本地时间。为了确保日志时间戳的准确性,您可以使用timedatectl工具来检查和设置系统时区:

  • 列出可用时区
    timedatectl list-timezones
    
  • 设置时区
    sudo timedatectl set-timezone Asia/Shanghai
    
    Asia/Shanghai替换为您所需时区。
  • 查看当前时间状态
    timedatectl status
    

使用journalctl查看日志

查看所有日志

最基本的journalctl命令将显示系统中所有的日志条目:

journalctl

这会通过分页器(通常是less)显示所有日志,最旧的条目在顶部。

以UTC时间显示日志

如果您希望以协调世界时 (UTC) 而不是本地时间显示日志,可以使用--utc选项:

journalctl --utc

按时间过滤systemd日志

查看当前启动会话的日志

要查看系统最近一次启动(即当前启动会话)以来的所有日志条目,使用-b选项:

journalctl -b

访问以前的启动日志

默认情况下,systemd Journal可能只将日志存储在内存中。为了查看以前的启动日志,您需要启用日志的持久性存储。

  1. 启用日志持久性: 创建日志存储目录:

    sudo mkdir -p /var/log/journal
    

    或者,编辑journald的配置文件/etc/systemd/journald.conf,将Storage=设置为persistent

    # /etc/systemd/journald.conf
    [Journal]
    Storage=persistent
    

    修改后需要重启systemd-journald服务使配置生效:

    sudo systemctl restart systemd-journald
    
  2. 列出所有启动会话: 要查看系统所有的历史启动会话及其对应的偏移量和启动ID,使用--list-boots

    journalctl --list-boots
    

    输出示例:

    -2 b8c8f0d8b7a64e10b2c3d4e5f6a7b8c9 Fri 2023-10-27 10:00:00 UTC—Fri 2023-10-27 12:00:00 UTC
    -1 a1b2c3d4e5f67g8h9i0j1k2l3m4n5o6p Sat 2023-10-28 14:30:00 UTC—Sat 2023-10-28 16:00:00 UTC
     0 q1r2s3t4u5v6w7x8y9z0a1b2c3d4e5f6 Sun 2023-10-29 09:00:00 UTC—Sun 2023-10-29 11:00:00 UTC
    

    这里的-2, -1, 0是偏移量,0代表当前启动,-1代表上一次启动,以此类推。

  3. 查看特定启动的日志

    • 查看上一次启动的日志
      journalctl -b -1
      
    • 按启动ID查看日志
      journalctl -b b8c8f0d8b7a64e10b2c3d4e5f6a7b8c9
      
      b8c8f0d8b7a64e10b2c3d4e5f6a7b8c9替换为实际的启动ID。

按自定义日期和时间范围过滤

--since--until选项用于限制显示日志的时间范围。

  • 绝对时间格式:支持YYYY-MM-DD HH:MM:SS格式。
    journalctl --since "2023-10-27 17:15:00"
    journalctl --since "2023-10-27 17:15:00" --until "2023-10-27 18:00:00"
    
  • 相对时间表达式:支持“yesterday”、“today”、“now”或"1 hour ago"等易读的表达式。
    journalctl --since "yesterday"
    journalctl --since "09:00" --until "1 hour ago"
    

按服务、PID或用户过滤systemd日志

systemd服务单元查看日志

要查看特定systemd服务(例如Nginx)的日志,使用-u选项:

journalctl -u nginx.service

您可以同时指定多个服务单元来合并显示它们的日志:

journalctl -u nginx.service -u php-fpm.service --since today

按PID、UID或GID过滤

journalctl支持按进程ID (PID)、用户ID (UID) 或组ID (GID) 过滤日志。

  • 按PID
    journalctl _PID=8088
    
  • 按UID/GID:例如查找www-data用户(UID通常为33)的日志:
    journalctl _UID=33 --since today
    
  • 查看某个字段的所有可用值
    journalctl -F _GID
    
    所有可用的日志字段可以查阅man systemd.journal-fields

按可执行文件路径查看日志

显示与特定可执行文件相关的日志条目:

journalctl /usr/bin/bash

查看内核日志 (dmesg输出)

要查看通常在dmesg输出中找到的内核消息,可以使用-k--dmesg选项:

journalctl -k
# 或者
journalctl --dmesg

可以结合-b选项查看特定启动的内核日志:

journalctl -b -1 -k

按严重级别过滤日志

journalctl -p选项允许您显示指定优先级或更高优先级的日志消息。优先级从高到低依次为:

  • 0: emerg (紧急)
  • 1: alert (警报)
  • 2: crit (关键)
  • 3: err (错误)
  • 4: warning (警告)
  • 5: notice (通知)
  • 6: info (信息)
  • 7: debug (调试)

例如,查看当前启动中的所有错误及更高级别的日志:

journalctl -p err -b

自定义journalctl日志输出显示

控制输出长度和格式

  • 截断长行
    journalctl --no-full
    
    此选项会截断超出屏幕宽度的长行,使其更容易在终端中阅读。
  • 显示所有信息(包括不可打印字符)
    journalctl -a
    
    用于显示完整的日志字段,包括那些通常不可打印或难以阅读的字符。

禁用分页器

如果想将日志输出直接发送到标准输出(例如,为了管道到其他命令),可以禁用分页器:

journalctl --no-pager | grep "error"

不同的输出格式

使用-o [format_specifier]选项可以控制日志的输出格式,以便于集成或分析。

  • json:JSON格式,每行一个日志条目。
  • json-pretty:美化后的JSON格式,带有缩进,更易读。
  • short:默认的syslog风格输出。
  • verbose:显示日志条目的所有可用Journal字段。
  • 其他格式:catexportjson-sseshort-isoshort-monotonicshort-precise

示例:

journalctl -u nginx.service -o json-pretty

监控实时systemd日志

显示最近的日志条目

要显示最新的N条日志条目,使用-n选项(默认显示最近10条):

journalctl -n 20

这将显示最近的20条日志。

实时跟踪日志

类似于tail -fjournalctl -f命令可以实时显示新写入的日志:

journalctl -f

您也可以结合其他过滤条件进行实时跟踪:

journalctl -f -u apache2.service

管理和清理systemd Journal日志

随着时间的推移,systemd Journal可能会占用大量磁盘空间。journalctl提供了管理和清理日志的工具。

检查磁盘使用量

journalctl --disk-usage

此命令会显示Journal当前占用的磁盘空间总量。

删除旧日志

  • 按大小清除:删除旧日志条目,直到总磁盘空间达到指定大小。
    sudo journalctl --vacuum-size=1G
    
    此命令将删除最早的日志,直到总空间不大于1GB。
  • 按时间清除:删除早于指定时间的日志条目。
    sudo journalctl --vacuum-time=1years
    
    此命令将删除所有1年以前的日志。

配置磁盘空间限制

为了更持久地管理日志的磁盘占用,您可以编辑/etc/systemd/journald.conf文件,配置以下指令:

  • SystemMaxUse=:为持久存储(/var/log/journal)设置最大磁盘空间限制。
  • SystemKeepFree=:在持久存储中保留的最小空闲空间。
  • SystemMaxFileSize=:持久存储中单个日志文件的最大大小。
  • RuntimeMaxUse=:为临时存储(/run/log/journal,内存文件系统)设置最大磁盘空间限制。
  • RuntimeKeepFree=:在临时存储中保留的最小空闲空间。
  • RuntimeMaxFileSize=:临时存储中单个日志文件的最大大小。

修改配置文件后,请重启systemd-journald服务以应用更改。

journalctlsystemd Journal常见问题排查

journalctl不显示日志

  • 日志数据库为空或缺失:这可能是因为系统是新安装的、最小化环境,或者日志仅存储在内存中(非持久化)。
    • 解决方案:创建/var/log/journal目录并重启systemd-journald服务以启用持久性日志。
  • 日志服务未运行systemd-journald服务可能已停止。
    • 解决方案:检查服务状态systemctl status systemd-journald,如果未运行则启动或重启它:sudo systemctl start systemd-journald
  • 过滤器太窄:您可能使用了过于严格的过滤条件。
    • 解决方案:尝试不带任何标志运行journalctl,然后逐步添加过滤器,以确定是哪个过滤器导致的问题。
  • 日志已被轮换或删除:日志受systemd Journal的保留策略限制,旧日志可能已被自动清除。
    • 解决方案:检查/etc/systemd/journald.conf中的保留策略设置。

使用journalctl时“权限被拒绝”

  • 使用sudo:最简单直接的方法是使用sudo journalctl
  • 通过组成员身份授予访问权限:将您的用户添加到systemd-journal组,该组拥有读取日志的权限。
    sudo usermod -aG systemd-journal yourusername
    
    然后重新登录或重启会话以使更改生效。
  • 验证Journal目录权限:确保/var/log/journal目录的权限正确。它应该由root:systemd-journal拥有,并允许组读取和执行。
    sudo chown root:systemd-journal /var/log/journal
    sudo chmod 2755 /var/log/journal
    

重启后日志不持久

  • 系统配置为仅临时存储:日志可能被配置为仅存储在内存中的临时位置(/run/log/journal)。
    • 解决方案:创建/var/log/journal目录并重启journald服务,确保日志写入磁盘。
    • 解决方案:检查/etc/systemd/journald.conf文件中的Storage=指令,确保它被设置为persistent

调试失败的systemd服务

当一个systemd服务启动失败或行为异常时,journalctl是首选的调试工具。

  • 查看服务状态和最近日志
    systemctl status [service_name.service]
    
    此命令会显示服务的当前状态、PID以及最近的几行日志。
  • 查看完整日志历史
    journalctl -u [service_name.service]
    
    可以结合-b选项查看上次启动的日志:journalctl -u [service_name.service] -b -1
  • 调查故障上下文:使用时间过滤器(如--since "10 minutes ago")缩小日志范围,专注于故障发生前后的时间点。
  • 查看详细错误信息journalctl -xe会显示最近的日志条目,并突出显示潜在的错误和相关解释。

监控SSH登录尝试

journalctl可用于监控SSH服务器的登录活动。

  • 查看SSH日志
    journalctl -u ssh.service
    # 或者对于某些系统是
    journalctl -u sshd.service
    
  • 实时跟踪SSH活动
    journalctl -f -u ssh.service
    
  • 按登录事件过滤:结合grep过滤特定的关键词,例如“Failed password”或“Accepted password”来识别失败或成功的登录尝试。
    journalctl -u ssh.service | grep "Failed password"
    

dmesgjournalctl的区别

特性 dmesg journalctl
范围 仅限于内核环形缓冲区 (kernel ring buffer) 涵盖内核、systemd系统以及用户空间的所有日志
持久性 系统重启或缓冲区满后,日志会被清除 如果配置为持久化,日志会存储在磁盘上,可跨重启保留
元数据 无结构化元数据,仅时间戳和原始消息 包含丰富的结构化元数据(如systemd单元、PID、UID、优先级等)
过滤 功能有限,通常只能通过grep进行简单文本过滤 提供强大的过滤功能,可按时间、服务、PID、优先级等多种条件过滤
输出格式 原始、简单的文本输出 支持多种输出格式,如纯文本、JSON、JSON-pretty、shortverbose
权限 完整输出通常需要sudo权限 读取所有日志需要root权限或用户属于systemd-journal

简而言之,dmesg主要用于查看实时的低级内核日志,而journalctl则提供了一个更完整、结构化和持久的日志接口,涵盖了整个Linux系统的日志。

总结

systemd Journal及其强大的journalctl工具,为Linux系统提供了一个集中、灵活且高效的日志管理解决方案。通过掌握journalctl的各项功能,您可以轻松地查看、过滤、监控和管理系统日志,进行深入的故障分析和系统审计,从而更有效地维护和调试您的Linux环境。无论是日常的问题排查还是复杂的系统审计,journalctl都将是您不可或缺的利器。

关于

关注我获取更多资讯

公众号
📢 公众号
个人号
💬 个人号
使用 Hugo 构建
主题 StackJimmy 设计