脚本中Journalctl日志如何查询

wen 实用脚本 9

手把手教你查询Journalctl日志:从入门到脚本自动化实战

目录导读

  • Journalctl是什么?为什么比传统日志更强大?

    脚本中Journalctl日志如何查询

  • 基础查询:按时间、服务、优先级过滤

  • 进阶技巧:结合grep与正则表达式精准定位

  • 脚本实战:自动抓取关键错误并告警

  • 常见问题与解答(FAQ)


Journalctl是什么?为什么比传统日志更强大?

在现代Linux系统中(如CentOS 7+、Ubuntu 16.04+),systemd-journald 取代了传统的 syslog 守护进程。Journalctl 是其日志查看工具,具备以下优势:

  • 结构化存储:日志以二进制格式保存,包含时间戳、进程ID、优先级等元数据,支持精确过滤。
  • 自动轮转压缩:日志文件按大小或时间自动轮转,默认持久化至/var/log/journal
  • 低资源占用:相比rsyslog需要额外配置,journald开箱即用,适合容器和嵌入式环境。

场景示例:当你写脚本监控Nginx或SSH登录失败时,journalctl -u nginx.service 比直接tail -f /var/log/nginx/access.log 更易获取结构化错误(如连接超时、证书错误),且无需担心日志被手动删除。


基础查询:按时间、服务、优先级过滤

1 时间范围过滤(脚本中最常用)

# 最近5分钟内的日志(适合监控近期错误)
journalctl --since "5 minutes ago" --until "now"
# 指定日期范围(格式:YYYY-MM-DD HH:MM:SS)
journalctl --since "2025-01-10 09:00" --until "2025-01-10 18:00"

2 按服务单元(unit)过滤

# 精确监控某个systemd服务
journalctl -u nginx.service -u mysql.service
# 配合时间过滤:最近1小时nginx日志
journalctl -u nginx.service --since "1 hour ago"

3 按优先级过滤(数值越低越严重)

优先级 数字 典型场景
emerg 0 系统崩溃
alert 1 需立即修复
crit 2 严重错误
err 3 一般错误
warning 4 警告
notice 5 正常重要事件
info 6 一般信息
debug 7 调试信息
# 仅显示错误及以上级别(ERROR+CRIT+ALERT+EMERG)
journalctl -p err -u sshd.service
# 排除debug和info(显示warning及以上)
journalctl -p warning -u systemd-networkd.service

4 实时跟踪(类似tail -f)

journalctl -u myapp.service -f

进阶技巧:结合grep与正则表达式精准定位

1 输出格式控制(方便脚本解析)

# 只输出消息体(去除元数据)
journalctl -u myapp.service --no-pager --output=json | jq '.MESSAGE'
# 自定义输出字段(示例:只显示进程ID和消息)
journalctl -u myapp.service --output=verbose | grep -oP 'PID=\d+|MESSAGE=.*'

2 使用grep对结果二次过滤

# 查找含"timeout"或"error"的行(大小写不敏感)
journalctl -u nginx.service --since "30 min ago" | grep -iE "(timeout|error)"
# 排除包含"normal"的日志
journalctl -u app.service -p err | grep -v "normal_operation"

3 正则表达式精准匹配(适用于脚本)

假设你要检测IP地址重复登录失败

# 查找SSH失败登录(假设日志格式类似:Failed password for root from 192.168.1.1)
journalctl -u sshd.service -p err --since "1 hour ago" | \
    grep -Po '(?<=from )\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -nr

输出5 192.168.1.1 表示该IP在1小时内失败5次,可用于后续封禁脚本。


脚本实战:自动抓取关键错误并告警

下面是一个完整的Shell脚本示例,用于每5分钟扫描所有服务的error级别日志,发现新错误时发送邮件或写入文件。

1 脚本文件 journal_alert.sh

#!/bin/bash
# 功能:最近5分钟内所有服务的错误日志监控
# 用法:添加cron任务 */5 * * * * /path/to/journal_alert.sh
LOG_FILE="/var/log/journal_alert.log"
LAST_CHECK_FILE="/tmp/journal_last_check"  # 记录上次检查时间
CURRENT_TIME=$(date "+%Y-%m-%d %H:%M:%S")
# 初始化时间戳(首次运行时从5分钟前开始)
if [ ! -f "$LAST_CHECK_FILE" ]; then
    echo "$(date -d '5 minutes ago' '+%Y-%m-%d %H:%M:%S')" > "$LAST_CHECK_FILE"
fi
LAST_TIME=$(cat "$LAST_CHECK_FILE")
# 查询错误日志(排除常见无意义信息)
ERR_LOG=$(journalctl -p err --since "$LAST_TIME" --until "$CURRENT_TIME" --no-pager | \
    grep -v "kernel:.*error" | grep -v "dbus-daemon:.*error" | head -100)
if [ -n "$ERR_LOG" ]; then
    echo "$CURRENT_TIME - 发现新错误:" >> "$LOG_FILE"
    echo "$ERR_LOG" >> "$LOG_FILE"
    echo "---" >> "$LOG_FILE"
    # 可选:发送邮件告警(需要提前配置mailx或msmtp)
    # echo "$ERR_LOG" | mail -s "服务器错误告警" admin@example.com
fi
# 更新检查时间
echo "$CURRENT_TIME" > "$LAST_CHECK_FILE"

2 设置cron定时任务

crontab -e
# 添加行(每5分钟执行一次)
*/5 * * * * /bin/bash /usr/local/bin/journal_alert.sh

3 脚本优化要点

  • 性能:通过 --since--until 限制范围,避免全量扫描,尤其适用于 /var/log/journal 大的场景。
  • 容错:使用 head -100 防止错误日志过多导致脚本卡死。
  • 无效过滤:根据业务忽略系统级噪音(如内核错误可通过 journalctl -p err -k 独立处理)。

常见问题与解答(FAQ)

Q1:journalctl 显示“Data from the specified time is not available”,怎么办?

A:通常因为/var/log/journal 持久化未启用,或日志已被轮转删除。
解决方案

  • 检查持久化:systemctl status systemd-journald,确保日志目录存在。
  • 通过 journalctl --list-boots 查看可用启动记录,若没有则需重启systemd-journald或调整/etc/systemd/journald.conf 中的 Storage=persistent

Q2:脚本中如何判断某服务最近是否重启过?

A:通过过滤StartedStopped事件:

journalctl -u nginx.service -p 6 --since "10 minutes ago" | grep -i "started"

如果输出为空,则说明服务在该时间段内未重启。

Q3:journalctl -f 在脚本中为什么无法退出?

A-f(follow)会持续阻塞直到手动中断,脚本应用时需去掉-f,使用--since控制时间窗口,若需实时分析,考虑使用journalctl -u xxx.service --output=json --follow 2>/dev/null | while read line; do ... done,但建议换用systemd-tmpfiles或C语言库。

Q4:如何清除旧日志释放磁盘空间?

A

# 保留最近2天日志(会删除更早的)
sudo journalctl --vacuum-time=2d
# 强制保留日志文件小于500MB
sudo journalctl --vacuum-size=500M
# 手动删除所有日志(谨慎!)
sudo rm -rf /var/log/journal/*
sudo systemctl restart systemd-journald

Q5:journalctlrsyslog 是否互斥?

A:不互斥,常见配置是systemd-journald负责收集所有日志,rsyslog通过imjournal模块读取journald日志并写入传统/var/log/messages,脚本中优先使用journalctl获取结构化数据,例如需要_EXE_SYSTEMD_UNIT字段时。


Journalctl是现代Linux日志管理的核心工具,将它与脚本结合可以实现:

  • 精准监控:通过时间、优先级、服务单元快速锁定问题。
  • 自动化告警:基于错误模式的检测和响应(如自动封禁IP、重启服务)。
  • 磁盘管理:利用--vacuum-*控制日志占用空间。

下一步建议:在脚本中引入journalctl --output=json,配合jq解析,可将日志数据直接推送至ELK或Prometheus,实现集中监控。

参考资料

  • man journalctl
  • systemd-journald.service 文档
  • 《Linux系统日志管理最佳实践》(O'Reilly)

抱歉,评论功能暂时关闭!