手把手教你查询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:通过过滤Started或Stopped事件:
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:journalctl 与 rsyslog 是否互斥?
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)