19 - 日志分析与监控(journald、rsyslog、logrotate)
前提条件
- 已完成 LVM、NFS/Samba 共享、备份配置(
/data可用于存放日志归档) - 以 root 身份登录,或 ops 用户执行
sudo -i切换至 root 环境 - 系统运行在 Debian 12 Bookworm
- 虚拟机环境:VMware Workstation Pro(建议充足磁盘空间以观察日志增长)
全局参数
主机名 linuxdc,IP 192.168.1.100/24,SSH 端口 2222,运维用户 ops
Debian 12 日志体系概览
| 组件 | 类型 | 存储位置 | 主要职责 |
|---|---|---|---|
systemd-journald |
二进制结构化日志 | /var/log/journal/(persistent)或内存(volatile) |
收集所有 systemd 单元、内核、启动日志 |
rsyslog |
文本日志守护进程 | /var/log/syslog、/var/log/auth.log 等 |
转发 journal 日志为文本,兼容传统工具 |
logrotate |
日志轮转工具 | 配置在 /etc/logrotate.d/ |
防止日志文件无限增长,自动压缩归档 |
三者协同:journald 采集所有日志 → rsyslog 读取 journal 输出为文本文件 → logrotate 定期压缩轮转文本日志文件。
详细步骤
1. journald — systemd 默认结构化日志
常用查询命令:
| 命令 | 说明 |
|---|---|
journalctl -b |
本次启动的所有日志 |
journalctl -b -1 |
上次启动的日志(排查崩溃根因) |
journalctl -u ssh -n 200 |
ssh 服务最近 200 行 |
journalctl -u ssh -f |
实时跟踪 ssh 日志 |
journalctl -p err -b |
本次启动 err 级别及以上日志 |
journalctl --since "2026-06-01" --until "2026-06-02" |
指定时间范围 |
journalctl --disk-usage |
查看日志磁盘占用 |
journalctl --vacuum-size=500M |
立即压缩至 500 MB 以内 |
配置持久化存储(默认 volatile,重启丢失):
mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal
编辑配置文件:
vim /etc/systemd/journald.conf
推荐生产配置:
[Journal]
Storage=persistent
Compress=yes
SystemMaxUse=10G
SystemKeepFree=20%
RuntimeMaxUse=2G
MaxRetentionSec=1month
journald 存储模式说明:
| 模式 | 配置值 | 行为 |
|---|---|---|
| 持久化 | Storage=persistent |
日志写入 /var/log/journal/,重启后保留 |
| 内存(volatile) | Storage=volatile |
日志写入 /run/log/journal/,重启后丢失 |
| 自动 | Storage=auto(默认) |
若 /var/log/journal/ 目录存在则持久化,否则 volatile |
应用配置:
systemctl restart systemd-journald
journalctl --disk-usage
检查点
ls /var/log/journal/ 显示以机器 ID 命名的目录,journalctl --disk-usage 显示实际占用空间。
2. rsyslog — 传统文本日志(兼容旧工具)
Debian 默认同时运行 rsyslog,将 journal 日志转发到 /var/log/ 下的文本文件。
主要日志文件:
| 文件路径 | 内容 |
|---|---|
/var/log/syslog |
系统综合日志(最常用) |
/var/log/auth.log |
认证日志(SSH 登录、sudo、su) |
/var/log/kern.log |
内核日志 |
/var/log/dpkg.log |
软件包安装记录 |
/var/log/fail2ban.log |
fail2ban 封禁记录 |
常用查看命令:
tail -f /var/log/syslog
tail -f /var/log/auth.log
grep "Failed password" /var/log/auth.log | tail -20
grep "sshd" /var/log/auth.log | grep "$(date '+%b %e')"
自定义 rsyslog 规则(将 sshd 日志单独写入文件):
vim /etc/rsyslog.d/10-custom.conf
添加内容:
# 将 sshd 的日志单独写入 /var/log/sshd.log
if $programname == 'sshd' then /var/log/sshd.log
& stop
重启 rsyslog 并验证:
systemctl restart rsyslog
# 触发一次 SSH 登录后
tail /var/log/sshd.log
检查点
SSH 登录后,/var/log/sshd.log 中出现对应的连接记录,同时 /var/log/auth.log 中不再包含 sshd 条目(被 & stop 截断)。
3. logrotate — 日志轮转与压缩
Debian 默认已安装 logrotate,由 systemd timer 每日触发。
查看当前配置:
logrotate -d /etc/logrotate.conf # 调试模式(不实际执行,仅预览)
ls /etc/logrotate.d/ # 查看各服务的轮转规则
logrotate 常用指令说明:
| 指令 | 说明 |
|---|---|
daily / weekly / monthly |
轮转频率 |
rotate 14 |
保留最近 14 份轮转文件 |
compress |
轮转后压缩为 .gz |
delaycompress |
本次轮转不压缩,下次轮转时才压缩(保留最新一份可读) |
missingok |
日志文件不存在时不报错 |
notifempty |
日志文件为空时跳过轮转 |
create 0640 user group |
轮转后创建新日志文件并设置权限 |
postrotate / endscript |
轮转后执行的命令(通常用于 reload 服务) |
sharedscripts |
多个文件匹配时只执行一次 postrotate 脚本 |
创建自定义轮转规则:
vim /etc/logrotate.d/myapp
内容:
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 ops ops
sharedscripts
postrotate
systemctl reload myapp 2>/dev/null || true
endscript
}
手动触发轮转测试:
# 先创建测试日志
mkdir -p /var/log/myapp
echo "test log entry" > /var/log/myapp/app.log
# 强制轮转(忽略时间条件)
logrotate -f /etc/logrotate.d/myapp
ls -la /var/log/myapp/
# 应看到 app.log(新空文件)和 app.log.1(轮转后的旧文件)
检查点
ls /var/log/myapp/ 显示 app.log(新建空文件)和 app.log.1(原日志内容)。再次触发后出现 app.log.2.gz(压缩归档)。
4. 日志监控与告警基础
实时监控 SSH 暴力破解尝试:
tail -f /var/log/auth.log | grep --line-buffered "Failed password"
统计今日失败登录 IP 排名:
grep "Failed password" /var/log/auth.log \
| grep "$(date '+%b %e')" \
| awk '{print $(NF-3)}' \
| sort | uniq -c | sort -rn | head -10
安装 logwatch 进行每日摘要报告:
apt install -y logwatch
logwatch --detail Med --service sshd --range today --output stdout
进阶监控方向
本章建立日志基础体系后,后续可扩展:Elasticsearch + Kibana(ELK 栈)集中日志分析、Grafana + Loki 轻量可视化、Prometheus + Alertmanager 指标告警,形成完整的可观测性平台。
实践任务
- 配置 journald 为
persistent模式,确认/var/log/journal/目录出现并有日志写入 - 用
journalctl -u ssh -f实时监控 SSH 日志,同时从另一台机器尝试登录,观察日志输出 - 查看
/var/log/auth.log,提取最近 10 条 SSH 登录成功记录(关键字Accepted) - 创建自定义 logrotate 规则,手动触发轮转,验证
/var/log/myapp/下出现轮转和压缩文件
自测问题
1. journald 的 Storage=persistent 和 volatile 的区别是什么?
| 模式 | 存储位置 | 重启后是否保留 | 适用场景 |
|---|---|---|---|
volatile |
/run/log/journal/(tmpfs) |
否,随重启清空 | 磁盘空间极度受限、日志敏感需重启后自动清除 |
persistent |
/var/log/journal/ |
是,跨重启保留 | 生产服务器,需要跨重启分析历史日志和崩溃根因 |
auto(默认) |
取决于目录是否存在 | 条件性保留 | 若手动创建 /var/log/journal/ 则自动切换为 persistent |
生产服务器应配置为 persistent,否则服务器意外重启后无法查看崩溃前的日志。
2. 为什么生产环境建议限制 journald 的 SystemMaxUse?
journald 默认会使用文件系统剩余空间的 10% 作为上限,对于 100 GB+ 的大磁盘这意味着 10 GB+ 的日志空间,在高流量服务或日志级别较低时可能迅速达到上限引发轮转,也可能反过来因日志量过大影响磁盘 I/O。显式设置 SystemMaxUse=10G + SystemKeepFree=20% 双重保障:前者限制日志总量上限,后者确保磁盘始终保留足够空闲空间(防止日志写满导致其他服务异常)。
3. logrotate 中的 delaycompress 选项有什么实际作用?
compress 在每次轮转后立即压缩旧日志(app.log.1.gz)。delaycompress 与 compress 配合使用,延迟一个轮转周期再压缩:本次轮转产生 app.log.1(未压缩),下次轮转时才将 app.log.1 压缩为 app.log.2.gz。
实际意义:保留最近一份轮转日志为可读文本,方便管理员用 tail、grep 等工具直接查看,无需先解压。对于需要频繁查阅近期日志的场景(如 Nginx 访问日志分析)非常实用。
4. 如何用 journalctl 只显示今天以来所有错误级别的日志?
# 方式一:使用 --since 指定时间范围
journalctl -p err --since "today"
# 方式二:使用 -b 限定本次启动(若今天已重启)
journalctl -p err -b
# 方式三:指定具体时间
journalctl -p err --since "2026-06-01 00:00:00"
-p err 等价于 -p 3,显示 err(3)、crit(2)、alert(1)、emerg(0) 四个级别的日志。若只看 err 不含更高严重级别,使用 -p err..err(但实际生产中通常希望看到所有严重问题,直接用 -p err 即可)。
总结
日志是系统的"黑匣子",journald + rsyslog + logrotate 构成 Debian 完整的日志体系。生产中优先用 journalctl 排查实时和历史问题,rsyslog 保证与传统工具的文本兼容性,logrotate 防止磁盘被日志写满。后续 Web 服务、数据库、容器章节中,日志路径配置和异常监控都将依赖这套体系,逐步形成"采集 → 存储 → 分析 → 告警 → 响应"的完整可观测性闭环。