跳转至

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 指标告警,形成完整的可观测性平台。

实践任务

  1. 配置 journald 为 persistent 模式,确认 /var/log/journal/ 目录出现并有日志写入
  2. journalctl -u ssh -f 实时监控 SSH 日志,同时从另一台机器尝试登录,观察日志输出
  3. 查看 /var/log/auth.log,提取最近 10 条 SSH 登录成功记录(关键字 Accepted
  4. 创建自定义 logrotate 规则,手动触发轮转,验证 /var/log/myapp/ 下出现轮转和压缩文件

自测问题

1. journald 的 Storage=persistentvolatile 的区别是什么?

模式 存储位置 重启后是否保留 适用场景
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)。delaycompresscompress 配合使用,延迟一个轮转周期再压缩:本次轮转产生 app.log.1(未压缩),下次轮转时才将 app.log.1 压缩为 app.log.2.gz

实际意义:保留最近一份轮转日志为可读文本,方便管理员用 tailgrep 等工具直接查看,无需先解压。对于需要频繁查阅近期日志的场景(如 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 服务、数据库、容器章节中,日志路径配置和异常监控都将依赖这套体系,逐步形成"采集 → 存储 → 分析 → 告警 → 响应"的完整可观测性闭环。