当前位置:首页>Linux>Linux日志管理体系:rsyslog + journald + logrotate 实战指南

Linux日志管理体系:rsyslog + journald + logrotate 实战指南

  • 2026-02-08 20:47:42
Linux日志管理体系:rsyslog + journald + logrotate 实战指南

Linux日志管理体系:rsyslog + journald + logrotate 实战指南

一、概述

1.1 背景介绍

线上故障排查,90%的时间花在翻日志上。日志管理做得好不好,直接决定了故障恢复的速度。我们团队之前处理过一次数据库主从切换故障,因为日志分散在十几台机器上、格式不统一、部分还被logrotate清掉了,排查花了将近4个小时。后来把日志体系重新梳理了一遍,同类故障的定位时间缩短到15分钟以内。

CentOS 7之后systemd引入了journald,和传统的rsyslog并存。很多运维搞不清两者的关系和配合方式,要么只用rsyslog忽略了journald的结构化查询能力,要么只看journalctl不知道日志落盘到了哪里。实际生产环境中,两者协同使用才是正确姿势。

本篇从rsyslog、journald、logrotate三个核心组件入手,覆盖日志收集、存储、轮转、远程转发的完整链路,所有配置都在CentOS 7/8和Ubuntu 20.04/22.04上线上验证过。

1.2 技术特点

  • rsyslog基于facility/severity的分类机制:沿用了传统syslog的分类体系,通过facility(设施)标识日志来源(kern、auth、cron、local0-local7等),通过severity(级别)标识严重程度(emerg到debug共8级)。这套机制虽然古老但非常实用,配合过滤规则可以精确控制每条日志的去向。rsyslog在此基础上扩展了基于属性和基于表达式的高级过滤,处理能力实测可达每秒20万条以上。

  • journald二进制结构化存储支持索引查询:journald把日志存成二进制格式,自带索引,支持按服务名、PID、时间范围、优先级等多维度组合查询。查某个服务最近1小时的错误日志,一条journalctl命令就搞定,不用grep翻文件。缺点是二进制格式不能直接用文本工具处理,磁盘损坏时恢复难度大。

  • 两者可协同工作互补:默认配置下journald收集所有systemd管理的服务日志,同时通过imjournal模块转发给rsyslog落盘为文本文件。这样既保留了journald的结构化查询能力,又有rsyslog的文本日志兜底。远程转发、日志归档这些事交给rsyslog更合适,实时查询用journalctl更方便。

1.3 适用场景

  • 单机日志规范化管理:中小规模环境(50台以内),每台机器本地做好日志分类、轮转、保留策略,配合journalctl做快速查询。这是最基础的场景,也是后续集中化日志的前提。日志分类不清晰的机器,接入ELK之后只会制造更多混乱。

  • 集中式日志收集架构:通过rsyslog的远程转发功能,把多台机器的日志汇聚到中心日志服务器。中等规模(50-500台)用rsyslog直接转发到中心rsyslog服务器就够了,成本低、稳定。我们团队管理的200多台机器就是这个方案,跑了3年没出过问题。

  • 合规审计与日志留存:金融、政务等行业对日志有明确的留存要求(通常6个月到1年)。需要配合logrotate做压缩归档,配合rsyslog做远程备份,确保日志不丢失、不被篡改。这个场景下建议开启rsyslog的RELP协议做可靠传输。

1.4 环境要求

组件
版本要求
说明
操作系统
CentOS 7+/RHEL 7+/Ubuntu 18.04+
需要systemd支持,CentOS 6用的是rsyslog+syslog-ng方案,不在本文范围
rsyslog
8.24+(推荐8.2102+)
CentOS 7自带8.24,功能够用;8.2102+支持更多输出模块和更好的性能
systemd/journald
219+(CentOS 7自带)
版本跟随systemd,一般不需要单独升级
logrotate
3.8+(系统自带)
系统自带版本即可,极少需要升级
磁盘空间
/var/log分区建议10GB+
生产环境日志量大的机器建议单独挂载/var/log分区,避免日志撑满根分区
内存
rsyslog常驻约30-80MB
开启队列缓存后内存占用会增加,按队列大小估算

二、详细步骤

2.1 准备工作

2.1.1 Linux日志体系架构

先搞清楚日志在系统里的流转路径,不然后面的配置改起来心里没底。

内核消息 ──→ /dev/kmsg ──→ rsyslog(imklog) ──→ /var/log/kern.log
                              ↓
systemd服务 ──→ journald ──→ rsyslog(imjournal) ──→ /var/log/messages
                  ↓                                    /var/log/secure
              二进制日志                                /var/log/cron
          /var/log/journal/                            /var/log/maillog
                                                       ...
应用程序 ──→ syslog() ──→ /dev/log ──→ rsyslog(imuxsock) ──→ 按规则分发

应用程序 ──→ 直接写文件 ──→ /var/log/app/xxx.log ──→ logrotate轮转

几个关键点:

  1. systemd管理的服务,stdout/stderr会被journald捕获,不需要应用自己处理日志文件
  2. 传统的syslog()调用通过/dev/log这个unix socket进入rsyslog
  3. journald默认会把日志转发给rsyslog,所以rsyslog的/var/log/messages里能看到systemd服务的日志
  4. 应用自己写的日志文件(如nginx的access.log),不经过rsyslog,需要logrotate单独管理

2.1.2 系统检查

# 检查系统版本
cat /etc/os-release

# 确认systemd版本
systemctl --version

# 检查rsyslog是否安装和运行
rpm -qa | grep rsyslog    # RHEL/CentOS
dpkg -l | grep rsyslog    # Ubuntu/Debian
systemctl status rsyslog

# 检查journald状态
systemctl status systemd-journald

# 查看当前日志占用空间
du -sh /var/log/
journalctl --disk-usage

# 检查/var/log分区剩余空间
df -h /var/log/

2.1.3 安装依赖

CentOS/RHEL系统rsyslog默认已安装,Ubuntu需要确认:

# CentOS/RHEL - 安装rsyslog及常用模块
sudo yum install -y rsyslog rsyslog-relp rsyslog-mmjsonparse

# Ubuntu/Debian - 安装rsyslog及常用模块
sudo apt install -y rsyslog rsyslog-relp rsyslog-mmjsonparse

# 确认logrotate已安装(一般系统自带)
which logrotate
logrotate --version

# 如果需要远程转发用RELP协议,确认模块已安装
rpm -qa | grep rsyslog-relp    # RHEL/CentOS
dpkg -l | grep rsyslog-relp    # Ubuntu/Debian

2.2 核心配置

2.2.1 rsyslog核心配置详解

rsyslog的主配置文件是/etc/rsyslog.conf,配置分为三大块:模块加载、全局指令、规则。

模块加载部分

# /etc/rsyslog.conf - 模块加载段

# 提供对本地系统日志的支持(通过/dev/log socket)
module(load="imuxsock"
       SysSock.Use="on"
       SysSock.Name="/dev/log"
       SysSock.RateLimit.Interval="5"
       SysSock.RateLimit.Burst="2000")

# 从journald读取日志
module(load="imjournal"
       StateFile="imjournal.state"
       IgnorePreviousMessages="off"
       DefaultSeverity="5"
       DefaultFacility="user")

# 内核日志
module(load="imklog")

# 标记消息(定期写入-- MARK --,用于确认rsyslog还活着)
module(load="immark" interval="600")

# TCP接收(如果本机是日志中心服务器才需要开启)
# module(load="imtcp" MaxSessions="500")
# input(type="imtcp" port="514" ruleset="remote")

# UDP接收
# module(load="imudp")
# input(type="imudp" port="514" ruleset="remote")

facility和severity级别

这是rsyslog分类日志的基础,必须搞清楚:

Facility(设施)- 标识日志来源:
  0  kern      内核消息
  1  user      用户级消息(默认)
  2  mail      邮件系统
  3  daemon    系统守护进程
  4  auth      认证/授权消息(login, su)
  5  syslog    rsyslog自身消息
  6  lpr       打印系统
  7  news      新闻系统
  8  uucp      UUCP子系统
  9  cron      定时任务
  10 authpriv  私有认证消息(ssh, sudo)
  11 ftp       FTP守护进程
  16-23 local0-local7  本地自定义(给应用用的)

Severity(级别)- 从高到低:
  0  emerg     系统不可用
  1  alert     必须立即处理
  2  crit      严重错误
  3  err       一般错误
  4  warning   警告
  5  notice    正常但值得注意
  6  info      信息
  7  debug     调试信息

生产环境建议:应用日志用local0-local7,不同应用分配不同的facility,方便分类存储。我们团队的分配方案是local0给nginx,local1给应用服务,local2给数据库相关,local3给监控脚本。

过滤规则配置

rsyslog支持三种过滤语法,从简单到复杂:

# 1. 传统选择器语法(最常用)
# 格式:facility.severity  action
# severity表示该级别及以上

# 所有设施的info及以上级别 → /var/log/messages(排除mail/authpriv/cron)
*.info;mail.none;authpriv.none;cron.none    /var/log/messages

# 认证相关日志
authpriv.*                                   /var/log/secure

# 邮件日志
mail.*                                       -/var/log/maillog

# cron日志
cron.*                                       /var/log/cron

# 紧急消息发给所有登录用户
*.emerg                                      :omusrmsg:*

# local0的所有日志(给nginx用)
local0.*                                     /var/log/nginx/syslog.log

# 2. 基于属性的过滤(RainerScript)
# 按程序名过滤
:programname, isequal, "sshd"                /var/log/sshd.log

# 按消息内容过滤
:msg, contains, "error"                      /var/log/error-all.log

# 按来源IP过滤(远程日志场景)
:fromhost-ip, startswith, "192.168.1."       /var/log/remote/lan.log

# 3. 基于表达式的过滤(最灵活)
if$programname == 'nginx' and $syslogseverity <= 3 then {
    action(type="omfile" file="/var/log/nginx/error.log")
    stop
}

文件名前面加-表示异步写入,不是每条日志都fsync,性能好但断电可能丢几条。生产环境对性能敏感的日志(如access log)建议加-,安全审计日志不要加。

模板定义

# 自定义日志格式模板
# 带毫秒时间戳的格式
template(name="precise"type="string"
    string="%timegenerated:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n")

# JSON格式(方便后续接入ELK)
template(name="json-syslog"type="list") {
    constant(value="{")
    constant(value="\"@timestamp\":\"")  property(name="timegenerated" dateFormat="rfc3339")
    constant(value="\",\"host\":\"")     property(name="hostname")
    constant(value="\",\"severity\":\"") property(name="syslogseverity-text")
    constant(value="\",\"facility\":\"") property(name="syslogfacility-text")
    constant(value="\",\"program\":\"")  property(name="programname")
    constant(value="\",\"pid\":\"")      property(name="procid")
    constant(value="\",\"message\":\"")  property(name="msg" format="jsonf")
    constant(value="\"}\n")
}

# 远程日志按主机名分目录存储
template(name="RemoteHost"type="string"
    string="/var/log/remote/%HOSTNAME%/%programname%.log")

# 应用模板到规则
*.info;mail.none;authpriv.none;cron.none    action(type="omfile" file="/var/log/messages" template="precise")

远程日志转发

# === 客户端配置(发送端)===

# TCP转发(推荐,比UDP可靠)
# @@表示TCP,@表示UDP
*.* @@192.168.1.100:514

# 带队列的TCP转发(防止网络中断时丢日志)
action(type="omfwd"
    target="192.168.1.100"
    port="514"
    protocol="tcp"
    action.resumeRetryCount="-1"
    queue.type="LinkedList"
    queue.filename="fwd_to_logserver"
    queue.maxDiskSpace="1g"
    queue.saveOnShutdown="on"
    queue.size="50000"
    queue.discardMark="48000"
    queue.discardSeverity="7"
    action.resumeInterval="10")

# RELP转发(最可靠,保证不丢日志)
module(load="omrelp")
action(type="omrelp"
    target="192.168.1.100"
    port="2514"
    action.resumeRetryCount="-1"
    queue.type="LinkedList"
    queue.filename="relp_to_logserver"
    queue.maxDiskSpace="2g"
    queue.saveOnShutdown="on")

# === 服务端配置(接收端)===

# TCP接收
module(load="imtcp" MaxSessions="1000")
input(type="imtcp" port="514" ruleset="remote")

# RELP接收
module(load="imrelp")
input(type="imrelp" port="2514" ruleset="remote")

# 远程日志处理规则集
ruleset(name="remote") {
# 按主机名分目录存储
    action(type="omfile" dynaFile="RemoteHost")
}

2.2.2 journald配置

journald的配置文件是/etc/systemd/journald.conf,改完需要重启journald生效。

# /etc/systemd/journald.conf
[Journal]
# 存储方式:persistent=持久化到/var/log/journal,volatile=仅内存,auto=有目录就持久化
# 生产环境必须设为persistent,不然重启后日志全丢
Storage=persistent

# 日志最大占用磁盘空间(持久化存储)
# 设太大会挤占业务空间,设太小查不到历史日志
# 实测500M-2G比较合理,根据机器日志量调整
SystemMaxUse=1G

# 单个日志文件最大大小
SystemMaxFileSize=100M

# 日志保留时间
# 生产环境建议30天,合规要求高的设更长
MaxRetentionSec=30day

# 内存中日志最大占用(volatile模式或持久化前的缓冲)
RuntimeMaxUse=200M

# 速率限制 - 防止某个服务疯狂刷日志拖垮系统
# 每30秒内最多记录10000条,超过的丢弃
RateLimitIntervalSec=30s
RateLimitBurst=10000

# 是否转发到syslog(rsyslog)
# 设为yes,journald收到的日志会转发给rsyslog
ForwardToSyslog=yes

# 是否转发到内核日志缓冲区
ForwardToKMsg=no

# 是否转发到控制台
ForwardToConsole=no

# 是否转发到wall
ForwardToWall=yes

# 压缩大于指定大小的日志条目
Compress=yes

# 是否给日志加密封印(需要FSS密钥)
Seal=no

改完配置后重启journald:

# 创建持久化存储目录(如果不存在)
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal

# 重启journald
sudo systemctl restart systemd-journald

# 验证持久化是否生效
ls -la /var/log/journal/
journalctl --disk-usage

这里有个坑:Storage=persistent设置后,如果/var/log/journal/目录不存在,journald不会自动创建。必须手动创建目录或者执行systemd-tmpfiles --create。我们线上有台机器就因为这个问题,以为开了持久化实际上日志一直在内存里,重启后全丢了。

journalctl常用查询命令

# 查看指定服务的日志
journalctl -u nginx.service

# 查看最近1小时的日志
journalctl --since "1 hour ago"

# 查看指定时间范围
journalctl --since "2024-01-15 10:00:00" --until "2024-01-15 12:00:00"

# 只看错误及以上级别
journalctl -p err

# 按PID查看
journalctl _PID=1234

# 按可执行文件路径查看
journalctl _EXE=/usr/sbin/sshd

# 实时跟踪(类似tail -f)
journalctl -f -u nginx.service

# 输出为JSON格式(方便脚本处理)
journalctl -u nginx.service -o json-pretty

# 查看内核日志
journalctl -k

# 查看本次启动的日志
journalctl -b 0

# 查看上次启动的日志(排查重启原因很有用)
journalctl -b -1

# 查看启动列表
journalctl --list-boots

2.2.3 rsyslog与journald协同配置

默认情况下CentOS 7/8的rsyslog通过imjournal模块从journald读取日志,这个协同关系需要理解清楚:

应用/服务 → journald(二进制存储)→ imjournal模块 → rsyslog → 文本日志文件
                                                          → 远程转发

确认协同配置正常:

# 检查rsyslog是否加载了imjournal模块
grep -n "imjournal" /etc/rsyslog.conf

# 正常应该看到类似这行:
# module(load="imjournal" StateFile="imjournal.state")

# 检查imjournal状态文件
ls -la /var/lib/rsyslog/imjournal.state

# 如果用的是imuxsock而不是imjournal(Ubuntu默认方式)
# journald通过/dev/log socket把日志传给rsyslog
grep -n "imuxsock" /etc/rsyslog.conf

两种协同模式的选择:

模式
配置方式
优点
缺点
适用场景
imjournal
rsyslog从journald读取
能获取journald的结构化字段
有状态文件,偶尔出现重复或丢失
CentOS 7/8默认,推荐
imuxsock
journald转发到/dev/log
简单直接,兼容性好
丢失journald的额外字段
Ubuntu默认,简单场景

生产环境建议保持系统默认的协同模式,不要随意切换。如果遇到imjournal的状态文件损坏导致日志重复,删除/var/lib/rsyslog/imjournal.state后重启rsyslog即可。

2.2.4 logrotate日志轮转配置

logrotate是日志轮转的标准工具,由crond每天触发执行。主配置文件/etc/logrotate.conf,各应用的轮转规则放在/etc/logrotate.d/目录下。

logrotate全局配置

# /etc/logrotate.conf

# 默认每周轮转
weekly

# 保留4份历史日志
rotate 4

# 轮转后创建新的空日志文件
create

# 使用日期作为轮转文件后缀(推荐,比数字后缀直观)
dateext
dateformat -%Y%m%d

# 压缩历史日志
compress

# 延迟一个周期再压缩(方便查看最近一次的轮转日志)
delaycompress

# 包含/etc/logrotate.d/目录下的配置
include /etc/logrotate.d

自定义应用日志轮转

# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    rotate 30
    missingok
    notifempty
    compress
    delaycompress
    dateext
    dateformat -%Y%m%d
    sharedscripts
    postrotate
# 给nginx发信号重新打开日志文件
if [ -f /var/run/nginx.pid ]; then
kill -USR1 $(cat /var/run/nginx.pid)
fi
    endscript
}
# /etc/logrotate.d/app-service
/var/log/app/*.log {
    daily
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    dateext
    dateformat -%Y%m%d
# copytruncate模式:复制当前日志后清空原文件
# 适用于不支持信号重载的应用(如某些Java应用)
    copytruncate
# 单个日志文件超过200M就轮转,不等到周期
    maxsize 200M
# 轮转后执行的脚本
    postrotate
# 通知监控系统
        logger -t logrotate "App log rotated"
    endscript
}

copytruncate vs create模式的选择

这个选择很关键,选错了会丢日志或者应用写不进日志:

模式
原理
优点
缺点
适用场景
create(默认)
重命名旧文件,创建新文件
不丢日志
应用需要重新打开文件描述符(通过信号或重启)
nginx、rsyslog等支持信号重载的服务
copytruncate
复制旧文件内容,然后清空原文件
应用无感知,不需要重载
复制和清空之间有时间窗口,可能丢几行日志
不支持信号重载的应用、Java应用

生产环境建议:能用create+postrotate发信号的就用create,实在不行再用copytruncate。copytruncate在日志量大的时候(比如每秒几千行),丢失的那几行可能包含关键信息。

2.3 启动和验证

2.3.1 启动服务

# 启动rsyslog
sudo systemctl start rsyslog
sudo systemctl enable rsyslog
sudo systemctl status rsyslog

# journald一般随系统启动,确认状态
sudo systemctl status systemd-journald

# 验证rsyslog配置文件语法
sudo rsyslogd -N1
# 输出 "rsyslogd: End of config validation run" 表示配置正确

# 如果修改了配置,重启rsyslog
sudo systemctl restart rsyslog

# 查看rsyslog启动日志,确认没有报错
journalctl -u rsyslog --since "5 minutes ago" --no-pager

2.3.2 功能验证

# 1. 验证本地日志写入
logger -p local0.info "Test message from logger command"
# 检查是否写入了对应的日志文件
tail -1 /var/log/messages

# 2. 验证指定facility的日志路由
logger -p local0.err "Test local0 error message"
# 如果配置了local0.*的规则,检查对应文件

# 3. 验证journald记录
journalctl --since "1 minute ago" | grep "Test message"

# 4. 验证日志轮转配置
# 手动执行logrotate测试(debug模式,不实际执行)
sudo logrotate -d /etc/logrotate.d/nginx

# 手动强制执行一次轮转
sudo logrotate -f /etc/logrotate.d/nginx

# 检查轮转结果
ls -la /var/log/nginx/

# 5. 验证远程转发(如果配置了的话)
# 在发送端执行
logger -p local0.info "Remote test message $(date)"
# 在接收端检查
tail -1 /var/log/remote/$(hostname)/local0.log

# 6. 检查rsyslog内部统计
sudo rsyslogd -N1 2>&1 | head -20

三、示例代码和配置

3.1 完整配置示例

3.1.1 生产级rsyslog.conf完整配置

这份配置在我们团队200+台CentOS 7/8服务器上跑了3年,经过多次迭代,覆盖了本地日志分类、远程转发、队列防丢失等场景。

# 文件路径:/etc/rsyslog.conf
# 生产环境rsyslog配置 - 适用于CentOS 7/8
# 最后修改:2024-01

#################
# 全局指令
#################

# 工作目录(队列文件、状态文件存放位置)
global(
    workDirectory="/var/lib/rsyslog"
    maxMessageSize="64k"
    preserveFQDN="on"
)

# 默认文件权限
module(load="builtin:omfile"
    fileOwner="root"
    fileGroup="adm"
    fileCreateMode="0640"
    dirCreateMode="0755")

#################
# 模块加载
#################

# 本地日志socket
module(load="imuxsock"
    SysSock.Use="on"
    SysSock.RateLimit.Interval="5"
    SysSock.RateLimit.Burst="2000")

# 从journald读取
module(load="imjournal"
    StateFile="imjournal.state"
    IgnorePreviousMessages="off")

# 内核日志
module(load="imklog")

# 标记消息,每10分钟写一次MARK
module(load="immark" interval="600")

# TCP接收模块(仅日志中心服务器开启,普通节点注释掉)
# module(load="imtcp" MaxSessions="1000")
# input(type="imtcp" port="514" ruleset="remote")

# RELP接收模块(仅日志中心服务器开启)
# module(load="imrelp")
# input(type="imrelp" port="2514" ruleset="remote")

#################
# 模板定义
#################

# 精确时间戳格式(带毫秒)
template(name="precise"type="string"
    string="%timegenerated:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n")

# JSON格式(接入ELK用)
template(name="json-syslog"type="list") {
    constant(value="{")
    constant(value="\"@timestamp\":\"")  property(name="timegenerated" dateFormat="rfc3339")
    constant(value="\",\"host\":\"")     property(name="hostname")
    constant(value="\",\"severity\":\"") property(name="syslogseverity-text")
    constant(value="\",\"facility\":\"") property(name="syslogfacility-text")
    constant(value="\",\"program\":\"")  property(name="programname")
    constant(value="\",\"pid\":\"")      property(name="procid")
    constant(value="\",\"message\":\"")  property(name="msg" format="jsonf")
    constant(value="\"}\n")
}

# 远程日志按主机名+程序名分目录
template(name="RemoteHostLog"type="string"
    string="/var/log/remote/%HOSTNAME%/%programname%.log")

# 远程日志按日期分目录
template(name="RemoteDateLog"type="string"
    string="/var/log/remote/%HOSTNAME%/%$year%-%$month%-%$day%/%programname%.log")

#################
# 本地日志规则
#################

# 内核日志
kern.*                                      /var/log/kern.log

# 认证日志(ssh登录、sudo操作等,安全审计必看)
authpriv.*                                  /var/log/secure

# 邮件日志(异步写入,前面加-)
mail.*                                      -/var/log/maillog

# cron日志
cron.*                                      /var/log/cron

# 紧急消息广播给所有登录用户
*.emerg                                     :omusrmsg:*

# 通用消息日志(排除已单独处理的facility)
*.info;mail.none;authpriv.none;cron.none    action(type="omfile"
                                                file="/var/log/messages"
                                                template="precise")

# local0 - nginx日志(通过syslog输出的部分)
local0.*                                    /var/log/nginx/syslog.log

# local1 - 应用服务日志
local1.*                                    /var/log/app/service.log

# local2 - 数据库相关日志
local2.*                                    /var/log/db/database.log

# local3 - 监控脚本日志
local3.*                                    /var/log/monitor/scripts.log

# 按程序名单独记录sshd日志(方便安全审计)
:programname, isequal, "sshd"               /var/log/sshd.log

# 记录所有error及以上级别到单独文件(快速定位问题)
*.err                                       /var/log/error-all.log

#################
# 远程转发(客户端配置)
#################

# TCP转发到日志中心,带磁盘队列防丢失
action(type="omfwd"
    target="log-center.internal.com"
    port="514"
    protocol="tcp"
    template="json-syslog"
    action.resumeRetryCount="-1"
    action.resumeInterval="10"
    queue.type="LinkedList"
    queue.filename="fwd_to_logcenter"
    queue.maxDiskSpace="1g"
    queue.saveOnShutdown="on"
    queue.size="50000"
    queue.discardMark="48000"
    queue.discardSeverity="7"
    queue.checkpointInterval="100"
    queue.timeoutEnqueue="0")

#################
# 远程日志接收规则集(仅日志中心服务器使用)
#################

# ruleset(name="remote") {
#     action(type="omfile"
#         dynaFile="RemoteHostLog"
#         template="precise"
#         queue.type="LinkedList"
#         queue.filename="remote_write"
#         queue.maxDiskSpace="2g"
#         queue.saveOnShutdown="on")
# }

3.1.2 自定义应用日志收集的rsyslog配置

把应用日志通过rsyslog收集,比应用自己写文件更灵活,可以统一做转发、过滤、格式化。

# 文件路径:/etc/rsyslog.d/10-app-collect.conf
# 功能:收集指定目录下的应用日志文件,转发到日志中心

# 加载文件输入模块
module(load="imfile")

# 监控Java应用日志
input(type="imfile"
    File="/opt/app/logs/application.log"
    Tag="java-app:"
    Severity="info"
    Facility="local1"
    PersistStateInterval="200"
    readTimeout="10"
    freshStartTail="on"
    reopenOnTruncate="on")

# 监控Java应用错误日志
input(type="imfile"
    File="/opt/app/logs/error.log"
    Tag="java-app-error:"
    Severity="err"
    Facility="local1"
    PersistStateInterval="100"
    freshStartTail="on"
    reopenOnTruncate="on")

# 监控多个应用日志(通配符)
input(type="imfile"
    File="/opt/apps/*/logs/*.log"
    Tag="multi-app:"
    Severity="info"
    Facility="local1"
    freshStartTail="on"
    reopenOnTruncate="on")

# 过滤和转发规则
if$syslogtag startswith 'java-app'then {
# 本地存一份
    action(type="omfile"
        file="/var/log/app/java-collected.log"
        template="precise")
# 转发到日志中心
    action(type="omfwd"
        target="log-center.internal.com"
        port="514"
        protocol="tcp"
        template="json-syslog")
    stop
}

几个注意点:

  1. freshStartTail="on" 表示首次监控时从文件末尾开始读,不读历史内容。生产环境建议开启,否则第一次启动会把整个日志文件重新发一遍。
  2. reopenOnTruncate="on" 配合logrotate的copytruncate模式使用,文件被截断后自动重新打开。
  3. PersistStateInterval 控制状态持久化频率,值越小越安全但IO开销越大,200是个平衡值。

3.1.3 logrotate完整配置脚本

#!/bin/bash
# 文件名:/usr/local/bin/setup-logrotate.sh
# 功能:一键部署标准化的logrotate配置
# 适用:CentOS 7/8, Ubuntu 20.04/22.04

set -euo pipefail

LOGROTATE_DIR="/etc/logrotate.d"

echo"=== 部署logrotate标准配置 ==="

# 备份现有配置
BACKUP_DIR="/etc/logrotate.d.bak.$(date +%Y%m%d%H%M%S)"
cp -r "$LOGROTATE_DIR""$BACKUP_DIR"
echo"已备份现有配置到 $BACKUP_DIR"

# 系统日志轮转配置
cat > "${LOGROTATE_DIR}/syslog" << 'EOF'
/var/log/messages
/var/log/secure
/var/log/maillog
/var/log/cron
/var/log/kern.log
/var/log/error-all.log
{
    daily
    rotate 30
    missingok
    notifempty
    compress
    delaycompress
    dateext
    dateformat -%Y%m%d
    sharedscripts
    postrotate
        /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
    endscript
}
EOF
echo"已配置系统日志轮转"

# Nginx日志轮转配置
cat > "${LOGROTATE_DIR}/nginx" << 'EOF'
/var/log/nginx/*.log {
    daily
    rotate 30
    missingok
    notifempty
    compress
    delaycompress
    dateext
    dateformat -%Y%m%d
    sharedscripts
    postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 $(cat /var/run/nginx.pid)
fi
    endscript
}
EOF
echo"已配置Nginx日志轮转"

# 应用日志轮转配置(copytruncate模式)
cat > "${LOGROTATE_DIR}/app-logs" << 'EOF'
/var/log/app/*.log
/opt/app/logs/*.log
{
    daily
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    dateext
    dateformat -%Y%m%d
    copytruncate
    maxsize 500M
    su root root
}
EOF
echo"已配置应用日志轮转"

# 远程日志轮转配置(日志中心服务器用)
cat > "${LOGROTATE_DIR}/remote-logs" << 'EOF'
/var/log/remote/*/*.log {
    daily
    rotate 60
    missingok
    notifempty
    compress
    delaycompress
    dateext
    dateformat -%Y%m%d
    sharedscripts
    postrotate
        /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
    endscript
}
EOF
echo"已配置远程日志轮转"

# 验证所有配置
echo""
echo"=== 验证配置 ==="
for conf in"${LOGROTATE_DIR}"/*; do
if logrotate -d "$conf" > /dev/null 2>&1; then
echo"[OK] $(basename $conf)"
else
echo"[FAIL] $(basename $conf) - 请检查配置"
        logrotate -d "$conf" 2>&1 | tail -5
fi
done

echo""
echo"部署完成。可以用 logrotate -d /etc/logrotate.d/xxx 测试单个配置"
echo"强制执行轮转:logrotate -f /etc/logrotate.d/xxx"

3.2 实际应用案例

案例一:日志分析统计脚本

场景描述:运维日常需要快速统计日志中的错误频率、访问TOP IP、异常时间段等信息。手动grep效率太低,写个脚本自动化。

实现代码

#!/bin/bash
# 文件名:/usr/local/bin/log-analyzer.sh
# 功能:日志分析统计工具
# 用法:log-analyzer.sh <日志文件> [分析类型]
# 分析类型:error-stat | top-ip | time-dist | all

set -euo pipefail

LOG_FILE="${1:?用法: $0 <日志文件> [error-stat|top-ip|time-dist|all]}"
ANALYSIS="${2:-all}"

if [ ! -f "$LOG_FILE" ]; then
echo"错误:文件 $LOG_FILE 不存在"
exit 1
fi

TOTAL_LINES=$(wc -l < "$LOG_FILE")
echo"=========================================="
echo"日志分析报告"
echo"文件:$LOG_FILE"
echo"总行数:$TOTAL_LINES"
echo"文件大小:$(du -h "$LOG_FILE" | awk '{print $1}')"
echo"时间范围:$(head -1 "$LOG_FILE" | awk '{print $1, $2}') ~ $(tail -1 "$LOG_FILE" | awk '{print $1, $2}')"
echo"=========================================="

# 错误统计
error_stat() {
echo""
echo"--- 错误级别统计 ---"
echo"EMERG  : $(grep -ci 'emerg' "$LOG_FILE" 2>/dev/null || echo 0)"
echo"ALERT  : $(grep -ci 'alert' "$LOG_FILE" 2>/dev/null || echo 0)"
echo"CRIT   : $(grep -ci 'crit' "$LOG_FILE" 2>/dev/null || echo 0)"
echo"ERROR  : $(grep -ci 'error\|err\b' "$LOG_FILE" 2>/dev/null || echo 0)"
echo"WARNING: $(grep -ci 'warn' "$LOG_FILE" 2>/dev/null || echo 0)"

echo""
echo"--- 最近20条错误 ---"
    grep -i 'error\|crit\|alert\|emerg'"$LOG_FILE" | tail -20

echo""
echo"--- 错误关键词TOP10 ---"
    grep -ioP '(?:error|fail|refused|denied|timeout|unreachable)\S*'"$LOG_FILE" \
        | sort | uniq -c | sort -rn | head -10
}

# TOP IP统计(适用于包含IP的日志,如auth.log、access.log)
top_ip() {
echo""
echo"--- 访问IP TOP20 ---"
    grep -oP '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'"$LOG_FILE" \
        | sort | uniq -c | sort -rn | head -20

echo""
echo"--- 失败登录IP TOP10 ---"
    grep -i 'failed\|failure\|invalid'"$LOG_FILE" \
        | grep -oP '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' \
        | sort | uniq -c | sort -rn | head -10
}

# 时间分布统计
time_dist() {
echo""
echo"--- 每小时日志量分布 ---"
    awk '{print $3}'"$LOG_FILE" \
        | grep -oP '^\d{2}' \
        | sort | uniq -c | sort -k2 \
        | awk '{printf "%s:00  %6d  ", $2, $1; for(i=0;i<$1/100;i++) printf "#"; print ""}'
}

case"$ANALYSIS"in
    error-stat) error_stat ;;
    top-ip)     top_ip ;;
    time-dist)  time_dist ;;
    all)        error_stat; top_ip; time_dist ;;
    *)          echo"未知分析类型:$ANALYSIS"exit 1 ;;
esac

echo""
echo"=========================================="
echo"分析完成:$(date '+%Y-%m-%d %H:%M:%S')"
echo"=========================================="

运行结果

==========================================
日志分析报告
文件:/var/log/secure
总行数:15823
文件大小:1.8M
时间范围:Jan 15 00:01:02 ~ Jan 15 23:59:58
==========================================

--- 错误级别统计 ---
EMERG  : 0
ALERT  : 0
CRIT   : 2
ERROR  : 47
WARNING: 12

--- 访问IP TOP20 ---
   3842 192.168.1.50
   1205 10.0.0.15
    892 172.16.0.100
    ...

--- 每小时日志量分布 ---
00:00     342  ###
01:00     128  #
02:00      95
03:00      87
...
10:00    2105  #####################
11:00    1893  ##################

案例二:日志脱敏处理

场景描述:日志中可能包含手机号、身份证号、银行卡号等敏感信息。合规要求这些信息在存储和转发前必须脱敏。通过rsyslog的模板和属性替换功能实现实时脱敏。

实现步骤

  1. 在rsyslog中配置正则替换规则
  2. 对匹配到的敏感信息进行掩码处理
  3. 脱敏后的日志再写入文件或转发

rsyslog脱敏配置

# 文件路径:/etc/rsyslog.d/20-desensitize.conf
# 功能:日志脱敏 - 手机号、身份证号、银行卡号

# 加载正则替换模块
module(load="mmexternal")

# 方案一:使用mmnormalize + 自定义脚本(推荐,灵活性高)
# 需要配合外部脚本实现

# 方案二:使用模板中的正则替换(rsyslog 8.32+支持)
# 手机号脱敏:13812345678 → 138****5678
template(name="desensitized"type="string"
    string="%timegenerated:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::regex-replace(/(1[3-9][0-9])[0-9]{4}([0-9]{4})/\\1****\\2):::drop-last-lf%\n")

# 应用脱敏模板到指定日志
if$syslogfacility-text == 'local1'then {
    action(type="omfile"
        file="/var/log/app/service-desensitized.log"
        template="desensitized")
}

外部脱敏脚本(更灵活的方案)

#!/bin/bash
# 文件名:/usr/local/bin/log-desensitize.sh
# 功能:日志脱敏处理脚本
# 用法:可作为rsyslog的omprog外部程序,也可独立使用
# 独立用法:cat input.log | log-desensitize.sh > output.log

while IFS= read -r line; do
# 手机号脱敏:13812345678 → 138****5678
    line=$(echo"$line" | sed -E 's/(1[3-9][0-9])[0-9]{4}([0-9]{4})/\1****\2/g')

# 身份证号脱敏:110101199001011234 → 110101****1234
    line=$(echo"$line" | sed -E 's/([0-9]{6})[0-9]{8}([0-9]{4})/\1********\2/g')

# 银行卡号脱敏:6222021234567890123 → 6222****0123
    line=$(echo"$line" | sed -E 's/([0-9]{4})[0-9]{11,15}([0-9]{4})/\1****\2/g')

# 邮箱脱敏:user@example.com → u***@example.com
    line=$(echo"$line" | sed -E 's/([a-zA-Z0-9])[a-zA-Z0-9.]*(@[a-zA-Z0-9.-]+)/\1***\2/g')

echo"$line"
done

rsyslog配合omprog使用脱敏脚本

# /etc/rsyslog.d/21-omprog-desensitize.conf
module(load="omprog")

# 通过外部脚本处理后写入文件
if$syslogfacility-text == 'local1'then {
    action(type="omprog"
        binary="/usr/local/bin/log-desensitize.sh"
        output="/var/log/app/desensitized.log"
        confirmMessages="off"
        useTransactions="off")
}

案例三:集中日志架构快速搭建

场景描述:50台服务器需要把日志集中到一台日志中心服务器,用rsyslog原生方案,不上ELK(成本和复杂度都低很多)。

架构

节点1 ──┐
节点2 ──┤  TCP/514
节点3 ──┼──────────→ 日志中心服务器 ──→ /var/log/remote/主机名/程序名.log
...    ──┤                           ──→ logrotate轮转
节点50 ──┘                           ──→ 定期归档到NFS/对象存储

日志中心服务器配置

# /etc/rsyslog.d/00-server.conf

# 加载TCP接收模块
module(load="imtcp" MaxSessions="1000")
input(type="imtcp" port="514" ruleset="remote")

# 按主机名分目录的模板
template(name="RemoteLog"type="string"
    string="/var/log/remote/%HOSTNAME%/%programname%.log")

# 所有远程日志汇总文件
template(name="RemoteAll"type="string"
    string="/var/log/remote/all-hosts.log")

# 精确时间戳模板
template(name="RemoteFmt"type="string"
    string="%timegenerated:::date-rfc3339% [%HOSTNAME%] %syslogtag%%msg:::drop-last-lf%\n")

# 远程日志处理规则集
ruleset(name="remote") {
# 按主机名分目录存储
    action(type="omfile"
        dynaFile="RemoteLog"
        template="RemoteFmt"
        dynaFileCacheSize="100"
        ioBufferSize="64k"
        flushOnTXEnd="off"
        asyncWriting="on"
        flushInterval="1"
        queue.type="LinkedList"
        queue.filename="remote_disk_q"
        queue.maxDiskSpace="2g"
        queue.saveOnShutdown="on"
        queue.size="100000")

# 同时写一份汇总日志(方便全局搜索)
    action(type="omfile"
        file="/var/log/remote/all-hosts.log"
        template="RemoteFmt"
        asyncWriting="on"
        flushInterval="2")
}

客户端一键部署脚本

#!/bin/bash
# 文件名:deploy-log-client.sh
# 功能:在客户端节点部署rsyslog远程转发配置
# 用法:deploy-log-client.sh <日志中心IP>

LOG_SERVER="${1:?用法: $0 <日志中心服务器IP>}"

cat > /etc/rsyslog.d/99-forward.conf << EOF
# 转发所有日志到日志中心
action(type="omfwd"
    target="${LOG_SERVER}"
    port="514"
    protocol="tcp"
    template="RSYSLOG_SyslogProtocol23Format"
    action.resumeRetryCount="-1"
    action.resumeInterval="10"
    queue.type="LinkedList"
    queue.filename="fwd_to_center"
    queue.maxDiskSpace="500m"
    queue.saveOnShutdown="on"
    queue.size="10000")
EOF

# 验证配置
rsyslogd -N1
if [ $? -eq 0 ]; then
    systemctl restart rsyslog
echo"配置成功,已开始转发日志到 ${LOG_SERVER}:514"
# 发一条测试日志
    logger -t deploy-test "Log forwarding configured to ${LOG_SERVER}"
else
echo"配置有误,请检查"
    rm -f /etc/rsyslog.d/99-forward.conf
exit 1
fi

四、最佳实践和注意事项

4.1 最佳实践

4.1.1 性能优化

  • rsyslog异步写入和缓冲配置:默认rsyslog每条日志都同步写磁盘,高并发场景下IO压力很大。实测在每秒5000条日志的场景下,开启异步写入后rsyslog的CPU占用从12%降到3%,磁盘IOPS从4800降到600。

    # /etc/rsyslog.d/01-performance.conf
    # 主消息队列优化
    main_queue(
        queue.type="LinkedList"
        queue.filename="main_q"
        queue.maxDiskSpace="1g"
        queue.saveOnShutdown="on"
        queue.size="100000"
        queue.discardMark="90000"
        queue.discardSeverity="7"
        queue.workerThreads="4"
        queue.dequeueBatchSize="1000"
        queue.timeoutEnqueue="0"
    )

    # 文件输出异步写入
    # 在action中添加以下参数:
    # asyncWriting="on"       开启异步
    # flushOnTXEnd="off"      不在每个事务结束时flush
    # flushInterval="1"       每1秒flush一次
    # ioBufferSize="64k"      IO缓冲区64KB
  • journald速率限制调优:默认的速率限制(每30秒1万条)对大多数场景够用,但如果应用在异常时会短时间爆发大量日志,需要适当调高。我们有个Java服务在GC风暴时30秒内能产生5万条日志,默认限制下4万条被丢弃了,排查问题时关键信息全没了。

    # /etc/systemd/journald.conf
    [Journal]
    RateLimitIntervalSec=30s
    RateLimitBurst=50000

    改完执行 systemctl restart systemd-journald 生效。这个参数改大了会增加磁盘IO,根据实际日志量调整,别一上来就设成0(关闭限制)。

  • logrotate使用dateext避免文件名冲突:默认的数字后缀(.1 .2 .3)在手动执行logrotate时容易出现文件名冲突。用dateext后缀格式为messages-20240115,直观且不会冲突。

    # 在logrotate配置中添加
    dateext
    dateformat -%Y%m%d
    # 如果同一天可能轮转多次(配合maxsize使用),加上时间
    dateformat -%Y%m%d-%H%M%S

4.1.2 安全加固

  • 限制日志文件权限:日志文件中可能包含敏感信息(密码、token、IP地址),权限不能太松。

    # rsyslog创建文件的默认权限
    # 在rsyslog.conf的全局配置中设置
    module(load="builtin:omfile"
        fileOwner="root"
        fileGroup="adm"
        fileCreateMode="0640"
        dirCreateMode="0750")

    # 修复现有日志文件权限
    chmod 640 /var/log/messages /var/log/secure /var/log/cron
    chown root:adm /var/log/messages /var/log/secure /var/log/cron

    # 敏感日志(如secure)可以设置更严格的权限
    chmod 600 /var/log/secure
  • rsyslog远程传输加密:日志通过网络传输时,明文TCP/UDP容易被嗅探。生产环境如果日志中有敏感信息,必须用TLS加密。

    # 客户端TLS转发配置
    global(
        defaultNetstreamDriverCAFile="/etc/pki/rsyslog/ca.pem"
        defaultNetstreamDriverCertFile="/etc/pki/rsyslog/client-cert.pem"
        defaultNetstreamDriverKeyFile="/etc/pki/rsyslog/client-key.pem"
    )

    action(type="omfwd"
        target="log-center.internal.com"
        port="6514"
        protocol="tcp"
        streamDriver="gtls"
        streamDriverMode="1"
        streamDriverAuthMode="x509/name"
        streamDriverPermittedPeers="log-center.internal.com")
  • 防止日志被篡改:对于安全审计场景,本地日志可能被入侵者删除或修改。建议同时转发到远程日志服务器,并且远程服务器上的日志设为只追加属性。

    # 在日志服务器上,给日志文件设置只追加属性
    chattr +a /var/log/remote/*/secure.log

    # 查看属性
    lsattr /var/log/remote/*/secure.log

    # 注意:设了+a后logrotate无法正常轮转该文件
    # 需要在logrotate的prerotate中先去掉属性
    prerotate
        chattr -a /var/log/remote/*/secure.log 2>/dev/null || true
    endscript
    postrotate
        chattr +a /var/log/remote/*/secure.log 2>/dev/null || true
    endscript

4.1.3 高可用配置

  • rsyslog双中心转发:日志中心服务器单点故障会导致日志丢失。配置两台日志中心,rsyslog同时转发到两台。

    # 主日志中心
    action(type="omfwd"
        target="log-center-01.internal.com"
        port="514"
        protocol="tcp"
        action.resumeRetryCount="-1"
        queue.type="LinkedList"
        queue.filename="fwd_primary"
        queue.maxDiskSpace="1g"
        queue.saveOnShutdown="on")

    # 备日志中心
    action(type="omfwd"
        target="log-center-02.internal.com"
        port="514"
        protocol="tcp"
        action.resumeRetryCount="-1"
        queue.type="LinkedList"
        queue.filename="fwd_backup"
        queue.maxDiskSpace="1g"
        queue.saveOnShutdown="on")
  • 备份策略:日志中心服务器的日志定期归档到对象存储或NFS,保留策略按业务需求设定。我们的做法是热数据(7天内)放本地SSD,温数据(7-30天)放本地HDD,冷数据(30天以上)压缩后传到对象存储。

4.2 注意事项

4.2.1 配置注意事项

rsyslog配置文件的语法错误不会导致服务启动失败,但会导致部分规则不生效。改完配置一定要用 rsyslogd -N1 验证语法,不要直接restart碰运气。

  • /var/log分区必须单独挂载或者设置磁盘配额。日志撑满根分区会导致整个系统不可用,这个事故我们经历过两次,每次都是半夜被叫起来处理。
  • logrotate的postrotate脚本如果执行失败,不会回滚轮转操作。脚本里的命令要加错误处理,特别是kill信号那行,进程不存在时kill会报错。
  • journald的Storage=volatile模式下日志只在内存中,重启就没了。生产环境千万别用这个模式,除非你明确知道自己在做什么。

4.2.2 常见错误

错误现象
原因分析
解决方案
rsyslog启动后/var/log/messages不更新
imjournal模块状态文件损坏,或SELinux阻止写入
删除/var/lib/rsyslog/imjournal.state后重启rsyslog;检查ausearch -m avc -ts recent
logrotate执行后应用写不进日志
使用create模式但postrotate没有通知应用重新打开文件
在postrotate中发送正确的信号(如nginx用USR1,rsyslog用HUP)
远程转发日志丢失
使用UDP协议,网络抖动时丢包;或队列满了被丢弃
改用TCP或RELP协议;增大queue.maxDiskSpace
journalctl查不到历史日志
Storage未设为persistent,或日志被MaxRetentionSec清理
检查journald.conf的Storage设置;调整保留时间
rsyslog CPU占用异常高
正则表达式过滤规则写得太复杂,或日志量突增
优化过滤规则,把高频匹配的规则放前面;开启异步写入
logrotate报错"error: skipping because parent directory has insecure permissions"
日志文件的父目录权限不对(其他用户可写)
chmod 755 /var/log/xxx
 确保目录权限正确;或在logrotate配置中加su root root

4.2.3 兼容性问题

  • CentOS 7 vs CentOS 8/9的rsyslog差异:CentOS 7自带rsyslog 8.24,不支持一些新语法(如mmexternal模块的部分参数)。CentOS 8自带rsyslog 8.2102,功能更完整。如果需要在CentOS 7上用新功能,可以从rsyslog官方仓库安装新版本:

    # CentOS 7安装rsyslog 8.2102+
    curl -o /etc/yum.repos.d/rsyslog.repo \
        https://www.rsyslog.com/repos/v8-stable/rsyslog-v8-stable-centos7.repo
    yum install -y rsyslog
  • Ubuntu和CentOS的日志路径差异:Ubuntu默认用/var/log/syslog而不是/var/log/messages,认证日志在/var/log/auth.log而不是/var/log/secure。写跨平台的监控脚本时要注意这个差异。

  • systemd版本差异:CentOS 7的systemd 219不支持journalctl的部分参数(如--output=short-iso-precise),CentOS 8的systemd 239支持。跨版本使用时注意检查参数兼容性。


五、故障排查和监控

5.1 故障排查

5.1.1 日志查看

# 查看rsyslog自身日志(rsyslog出问题时第一个看的地方)
journalctl -u rsyslog --since "30 minutes ago" --no-pager

# 查看rsyslog内部状态(需要先开启统计模块)
# 在rsyslog.conf中添加:
# module(load="impstats" interval="60" severity="7" log.syslog="off" log.file="/var/log/rsyslog-stats.log")
tail -20 /var/log/rsyslog-stats.log

# 查看系统日志
tail -f /var/log/messages

# 查看认证日志(排查SSH登录问题)
tail -f /var/log/secure          # CentOS/RHEL
tail -f /var/log/auth.log        # Ubuntu/Debian

# 查看cron日志
tail -f /var/log/cron

# journalctl实时跟踪多个服务
journalctl -f -u rsyslog -u nginx -u sshd

# 查看指定优先级的日志
journalctl -p err --since "1 hour ago"

# 查看上次系统启动前的日志(排查重启原因)
journalctl -b -1 -p warning --no-pager

5.1.2 常见问题排查

问题一:rsyslog不写日志,/var/log/messages不更新

这是最常见的问题,排查思路按优先级:

# 第1步:确认rsyslog进程在运行
systemctl status rsyslog
ps aux | grep rsyslog

# 第2步:检查配置文件语法
rsyslogd -N1
# 如果报错,根据错误信息修复配置

# 第3步:检查SELinux是否阻止
getenforce
# 如果是Enforcing,查看是否有拒绝记录
ausearch -m avc -ts recent | grep rsyslog
# 临时关闭SELinux测试(确认是SELinux问题后再写规则放行)
setenforce 0

# 第4步:检查imjournal状态文件
ls -la /var/lib/rsyslog/imjournal.state
# 如果文件异常大或损坏,删除后重启
rm -f /var/lib/rsyslog/imjournal.state
systemctl restart rsyslog

# 第5步:检查磁盘空间
df -h /var/log/
# 如果磁盘满了,rsyslog写不进去但不会报错

# 第6步:检查文件权限
ls -la /var/log/messages
# 确认rsyslog进程用户(通常是root)有写权限

# 第7步:手动发一条测试日志
logger "rsyslog test $(date)"
tail -1 /var/log/messages
# 如果这条能写进去,说明rsyslog本身没问题,是日志源的问题

解决方案

  1. 90%的情况是imjournal状态文件损坏,删除重启即可
  2. SELinux问题用audit2allow生成放行规则
  3. 磁盘满了先清理空间,再排查是哪个日志文件暴涨

问题二:journald日志丢失,journalctl查不到历史记录

# 第1步:检查存储模式
grep -i storage /etc/systemd/journald.conf
# 如果是volatile或auto(且/var/log/journal不存在),重启后日志就没了

# 第2步:检查持久化目录
ls -la /var/log/journal/
# 如果目录不存在,创建并重启journald
mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal
systemctl restart systemd-journald

# 第3步:检查日志保留策略
grep -i "MaxRetention\|SystemMaxUse\|SystemMaxFileSize" /etc/systemd/journald.conf
# SystemMaxUse设太小会导致旧日志被快速清理

# 第4步:检查速率限制
grep -i "RateLimit" /etc/systemd/journald.conf
# 如果RateLimitBurst太小,高并发时日志会被丢弃
# 查看是否有被丢弃的记录
journalctl | grep "Suppressed"

# 第5步:检查磁盘空间和inode
df -h /var/log/journal/
df -i /var/log/journal/

解决方案

  1. 设置Storage=persistent并创建/var/log/journal/目录
  2. SystemMaxUse生产环境建议设1G-2G
  3. RateLimitBurst根据实际日志量调整,别设太小

问题三:日志文件暴涨撑满磁盘

这个问题一旦发生就是P0级事故,根分区满了系统直接不可用。

# 紧急处理:快速定位大文件
du -sh /var/log/* | sort -rh | head -10

# 如果是某个日志文件特别大,先truncate释放空间
# 注意:不要用rm删除正在被写入的文件!rm后空间不会释放(进程还持有文件描述符)
# 正确做法是truncate
> /var/log/xxx.log
# 或者
truncate -s 0 /var/log/xxx.log

# 如果已经rm了文件但空间没释放,找到持有文件描述符的进程
lsof | grep deleted | grep "/var/log"
# 重启对应进程释放文件描述符

# 查看哪个进程在疯狂写日志
iotop -o -P
# 或者
lsof /var/log/xxx.log

# 紧急清理journald日志释放空间
journalctl --vacuum-size=200M
journalctl --vacuum-time=3d

# 清理已轮转的压缩日志
find /var/log -name "*.gz" -mtime +7 -delete
find /var/log -name "*.[0-9]" -mtime +7 -delete

根因排查和预防

  1. 检查logrotate是否正常执行:cat /var/lib/logrotate/logrotate.status
  2. 检查是否有应用在debug模式运行(debug日志量是info的10-50倍)
  3. 设置磁盘监控告警,/var/log使用率超过70%就告警
  4. 给/var/log单独挂载分区,就算撑满也不影响根分区

问题四:logrotate不生效

# 第1步:确认logrotate定时任务存在
# CentOS 7/8
cat /etc/cron.daily/logrotate
# 或者检查systemd timer(CentOS 8+)
systemctl status logrotate.timer
systemctl list-timers | grep logrotate

# 第2步:手动执行测试
logrotate -d /etc/logrotate.d/nginx
# -d是debug模式,只显示会做什么,不实际执行
# 看输出中是否有error

# 第3步:强制执行一次
logrotate -f /etc/logrotate.d/nginx
# 检查是否生成了轮转文件
ls -la /var/log/nginx/

# 第4步:检查状态文件
cat /var/lib/logrotate/logrotate.status
# 看对应日志文件的最后轮转时间
# 如果时间不对,可以手动编辑这个文件

# 第5步:常见原因
# a. 日志文件路径写错了(通配符不匹配)
# b. notifempty + 空日志文件 = 不轮转
# c. 文件权限问题(su指令不对)
# d. dateext冲突(同一天已经轮转过,文件名重复)

5.1.3 调试模式

# rsyslog调试模式启动(前台运行,输出详细信息)
# 先停掉正在运行的rsyslog
systemctl stop rsyslog

# 以调试模式启动
rsyslogd -dn 2>&1 | tee /tmp/rsyslog-debug.log

# 在另一个终端发测试日志
logger -p local0.info "debug test message"

# 查看调试输出中的处理流程
# 调试完成后Ctrl+C停止,重新启动正常模式
systemctl start rsyslog

# journald调试
# 查看journald的内部状态
journalctl --header
# 显示日志文件的详细信息(大小、条目数等)

# 验证journald配置
systemd-analyze cat-config systemd/journald.conf
# 显示最终生效的配置(合并了所有配置片段)

# logrotate调试
logrotate -v /etc/logrotate.conf
# -v 显示详细过程
logrotate -dv /etc/logrotate.d/nginx
# -d + -v 最详细的调试输出

5.2 性能监控

5.2.1 关键指标监控

# rsyslog进程资源占用
top -p $(pgrep rsyslogd) -bn1

# rsyslog内存详情
ps aux | grep rsyslogd | grep -v grep

# rsyslog打开的文件描述符数量(太多说明动态文件缓存太大)
ls -la /proc/$(pgrep rsyslogd)/fd | wc -l

# journald磁盘占用
journalctl --disk-usage

# /var/log分区使用率
df -h /var/log/

# /var/log目录各子目录大小
du -sh /var/log/* 2>/dev/null | sort -rh | head -15

# 日志写入速率(每秒新增行数,观察10秒)
for i in $(seq 1 10); do
    wc -l /var/log/messages
    sleep 1
done

# rsyslog队列积压情况(需要开启impstats模块)
grep "queue" /var/log/rsyslog-stats.log | tail -5

# 检查rsyslog是否有丢弃日志
grep -i "discarded" /var/log/rsyslog-stats.log | tail -5

5.2.2 监控指标说明

指标名称
正常范围
告警阈值
说明
rsyslog CPU使用率
0-5%
>15%
持续高CPU说明日志量过大或规则太复杂
rsyslog内存使用
30-100MB
>500MB
内存高通常是队列积压导致
/var/log分区使用率
<70%
>80%
超过80%必须立即处理
journald磁盘占用
<SystemMaxUse设定值
>设定值的90%
正常情况journald会自动清理
rsyslog队列大小
<1000
>10000
队列积压说明下游处理不过来
日志写入速率
<5000条/秒
>10000条/秒
突增通常是应用异常
丢弃日志数
0
>0
任何丢弃都需要排查原因
logrotate执行状态
每日成功
连续2天未执行
检查crond或logrotate.timer

5.2.3 Prometheus监控规则

# prometheus-rules/rsyslog-alerts.yml
# rsyslog和日志系统监控告警规则
# 需要配合node_exporter和自定义exporter使用

groups:
-name:log_system_alerts
interval:60s
rules:
# /var/log分区使用率告警
-alert:VarLogDiskUsageHigh
expr:|
          (1 - node_filesystem_avail_bytes{mountpoint="/var/log"}
          / node_filesystem_size_bytes{mountpoint="/var/log"}) * 100 > 80
for:5m
labels:
severity:warning
annotations:
summary:"/var/log分区使用率超过80%"
description:"主机 {{ $labels.instance }} 的/var/log分区使用率为 {{ $value | printf \"%.1f\" }}%"

-alert:VarLogDiskUsageCritical
expr:|
          (1 - node_filesystem_avail_bytes{mountpoint="/var/log"}
          / node_filesystem_size_bytes{mountpoint="/var/log"}) * 100 > 90
for:2m
labels:
severity:critical
annotations:
summary:"/var/log分区使用率超过90%,需要立即处理"
description:"主机 {{ $labels.instance }} 的/var/log分区使用率为 {{ $value | printf \"%.1f\" }}%,有撑满风险"

# 根分区使用率告警(日志可能在根分区)
-alert:RootDiskUsageHigh
expr:|
          (1 - node_filesystem_avail_bytes{mountpoint="/"}
          / node_filesystem_size_bytes{mountpoint="/"}) * 100 > 85
for:5m
labels:
severity:warning
annotations:
summary:"根分区使用率超过85%"
description:"主机 {{ $labels.instance }} 根分区使用率 {{ $value | printf \"%.1f\" }}%,检查是否日志暴涨"

# rsyslog进程存活检查
-alert:RsyslogDown
expr:node_systemd_unit_state{name="rsyslog.service",state="active"}!=1
for:1m
labels:
severity:critical
annotations:
summary:"rsyslog服务未运行"
description:"主机 {{ $labels.instance }} 的rsyslog服务停止,日志可能丢失"

# rsyslog CPU使用率异常
-alert:RsyslogHighCPU
expr:|
          rate(namedprocess_namegroup_cpu_seconds_total{groupname="rsyslogd"}[5m]) * 100 > 15
for:10m
labels:
severity:warning
annotations:
summary:"rsyslog CPU使用率异常"
description:"主机 {{ $labels.instance }} rsyslog CPU使用率持续超过15%"

自定义日志监控脚本(配合Prometheus textfile collector)

#!/bin/bash
# 文件名:/usr/local/bin/log-metrics.sh
# 功能:采集日志系统指标,输出Prometheus格式
# 配合node_exporter的textfile collector使用
# crontab: * * * * * /usr/local/bin/log-metrics.sh

METRICS_FILE="/var/lib/node_exporter/textfile_collector/log_metrics.prom"
TEMP_FILE="${METRICS_FILE}.tmp"

{
# /var/log目录总大小(字节)
    VAR_LOG_SIZE=$(du -sb /var/log/ 2>/dev/null | awk '{print $1}')
echo"log_var_log_size_bytes ${VAR_LOG_SIZE:-0}"

# journald占用空间(字节)
    JOURNAL_SIZE=$(journalctl --disk-usage 2>/dev/null | grep -oP '\d+\.\d+[MGK]' | head -1)
# 转换为字节
ifecho"$JOURNAL_SIZE" | grep -q 'G'then
        JOURNAL_BYTES=$(echo"$JOURNAL_SIZE" | sed 's/G//' | awk '{printf "%.0f", $1*1024*1024*1024}')
elifecho"$JOURNAL_SIZE" | grep -q 'M'then
        JOURNAL_BYTES=$(echo"$JOURNAL_SIZE" | sed 's/M//' | awk '{printf "%.0f", $1*1024*1024}')
else
        JOURNAL_BYTES=0
fi
echo"log_journald_size_bytes ${JOURNAL_BYTES}"

# rsyslog进程状态(1=运行,0=停止)
if systemctl is-active rsyslog >/dev/null 2>&1; then
echo"log_rsyslog_running 1"
else
echo"log_rsyslog_running 0"
fi

# 最近1分钟的错误日志数量
    ERROR_COUNT=$(journalctl --since "1 minute ago" -p err --no-pager 2>/dev/null | wc -l)
echo"log_error_count_1m ${ERROR_COUNT}"

# 各主要日志文件大小
for logfile in messages secure cron maillog; do
if [ -f "/var/log/${logfile}" ]; then
            SIZE=$(stat -c%s "/var/log/${logfile}" 2>/dev/null || echo 0)
echo"log_file_size_bytes{file=\"${logfile}\"} ${SIZE}"
fi
done

} > "$TEMP_FILE"

mv "$TEMP_FILE""$METRICS_FILE"

5.3 备份与恢复

5.3.1 备份策略

#!/bin/bash
# 文件名:/usr/local/bin/log-backup.sh
# 功能:日志备份脚本 - 压缩归档到指定目录或远程存储
# crontab: 0 2 * * * /usr/local/bin/log-backup.sh

set -euo pipefail

# 配置
BACKUP_DIR="/data/log-backup"
REMOTE_DIR="rsync://backup-server/log-archive"
RETENTION_DAYS=90
DATE=$(date +%Y%m%d)
HOSTNAME=$(hostname -s)

# 创建备份目录
mkdir -p "${BACKUP_DIR}/${DATE}"

echo"[$(date)] 开始日志备份..."

# 备份rsyslog文本日志(只备份已轮转的压缩文件)
echo"备份rsyslog日志..."
find /var/log -maxdepth 1 -name "*.gz" -newer "${BACKUP_DIR}/.last_backup" 2>/dev/null \
    | xargs -I{} cp {} "${BACKUP_DIR}/${DATE}/" 2>/dev/null || true

# 备份远程日志(日志中心服务器)
if [ -d /var/log/remote ]; then
echo"备份远程日志..."
    find /var/log/remote -name "*.gz" -newer "${BACKUP_DIR}/.last_backup" 2>/dev/null \
        | whileread f; do
            REL_PATH=$(dirname "$f" | sed 's|/var/log/remote/||')
            mkdir -p "${BACKUP_DIR}/${DATE}/remote/${REL_PATH}"
            cp "$f""${BACKUP_DIR}/${DATE}/remote/${REL_PATH}/"
done
fi

# 导出journald日志(最近24小时)
echo"导出journald日志..."
journalctl --since "24 hours ago" --no-pager \
    > "${BACKUP_DIR}/${DATE}/journald-${HOSTNAME}-${DATE}.log" 2>/dev/null
gzip "${BACKUP_DIR}/${DATE}/journald-${HOSTNAME}-${DATE}.log"

# 备份配置文件
echo"备份日志配置..."
tar czf "${BACKUP_DIR}/${DATE}/log-config-${DATE}.tar.gz" \
    /etc/rsyslog.conf \
    /etc/rsyslog.d/ \
    /etc/systemd/journald.conf \
    /etc/logrotate.conf \
    /etc/logrotate.d/ \
    2>/dev/null

# 同步到远程存储(可选)
# rsync -az "${BACKUP_DIR}/${DATE}/" "${REMOTE_DIR}/${HOSTNAME}/${DATE}/"

# 清理过期备份
echo"清理${RETENTION_DAYS}天前的备份..."
find "${BACKUP_DIR}" -maxdepth 1 -type d -mtime +${RETENTION_DAYS} -exec rm -rf {} \;

# 更新最后备份时间戳
touch "${BACKUP_DIR}/.last_backup"

# 统计备份大小
BACKUP_SIZE=$(du -sh "${BACKUP_DIR}/${DATE}" | awk '{print $1}')
echo"[$(date)] 备份完成,本次备份大小:${BACKUP_SIZE}"
echo"备份路径:${BACKUP_DIR}/${DATE}/"

5.3.2 恢复流程

  1. 停止相关服务

    sudo systemctl stop rsyslog
  2. 恢复配置文件

    # 解压配置备份
    tar xzf /data/log-backup/20240115/log-config-20240115.tar.gz -C /
    # 验证配置
    rsyslogd -N1
  3. 恢复日志文件(如果需要):

    # 解压日志到原位置
    cp /data/log-backup/20240115/*.gz /var/log/
    gunzip /var/log/*.gz
  4. 重启服务并验证

    sudo systemctl start rsyslog
    sudo systemctl status rsyslog
    # 发测试日志验证
    logger "Recovery test $(date)"
    tail -1 /var/log/messages

六、总结

6.1 技术要点回顾

  • rsyslog是Linux日志体系的核心:基于facility/severity的分类机制虽然古老但实用,配合模板和过滤规则可以精确控制每条日志的去向。生产环境必须掌握的配置:模块加载、过滤规则、模板定义、远程转发、队列防丢失。
  • journald提供结构化查询能力:二进制存储+索引让日志查询效率比grep高一个数量级。journalctl -u xxx -p err --since "1 hour ago" 这种组合查询在排障时非常高效。生产环境必须设置Storage=persistent并创建持久化目录。
  • logrotate是日志轮转的标准方案:create和copytruncate两种模式的选择直接影响日志完整性。能用create+postrotate信号的场景不要用copytruncate。dateext比数字后缀更直观,推荐默认开启。
  • 三者协同才是完整方案:journald负责收集systemd服务日志并提供查询接口,rsyslog负责分类存储和远程转发,logrotate负责轮转和清理。单独用任何一个都有短板。
  • 磁盘空间管理是日志运维的生命线:/var/log分区单独挂载、logrotate正常运行、journald空间限制、磁盘监控告警,这四个环节缺一个都可能导致磁盘撑满的事故。
  • 远程转发用TCP+队列,安全场景用TLS+RELP:UDP丢日志的概率在网络抖动时很高,生产环境不建议用。RELP协议保证不丢日志但性能略低,安全审计场景推荐。

6.2 进阶学习方向

  1. ELK/EFK集中日志平台:rsyslog原生方案适合中等规模,超过500台机器或者需要全文检索、可视化分析时,需要上Elasticsearch+Logstash/Fluentd+Kibana。rsyslog可以作为日志采集端,通过omelasticsearch模块直接写入ES。

    • 学习资源:Elastic官方文档 https://www.elastic.co/guide/
    • 实践建议:先在测试环境搭一套单节点ELK,把rsyslog的日志接进去,体验全文检索和Kibana看板
  2. 日志标准化和可观测性:结构化日志(JSON格式)比纯文本日志更容易被机器处理。推动开发团队统一日志格式(时间戳、级别、traceID、服务名、消息),配合分布式追踪系统(Jaeger、Zipkin)实现全链路排障。

    • 学习资源:OpenTelemetry项目 https://opentelemetry.io/
    • 实践建议:从一个核心服务开始推JSON格式日志,验证采集和查询链路
  3. 日志安全与合规:金融、医疗、政务行业对日志有严格的合规要求(等保2.0、GDPR等)。需要掌握日志脱敏、防篡改、留存策略、审计追踪等技术。

    • 学习资源:等保2.0日志审计要求、GDPR数据保护条例
    • 实践建议:梳理现有日志中的敏感信息,制定脱敏规则并在rsyslog中实现

6.3 参考资料

  • rsyslog官方文档 - 最权威的rsyslog配置参考,RainerScript语法详解
  • systemd-journald.service手册 - journald配置参数完整说明
  • logrotate手册 - logrotate所有配置指令说明
  • rsyslog GitHub仓库 - 源码和issue,排查疑难问题时有用

附录

A. 命令速查表

# === rsyslog相关 ===
rsyslogd -N1                              # 验证配置文件语法
rsyslogd -dn                              # 调试模式启动(前台)
systemctl restart rsyslog                  # 重启rsyslog
systemctl status rsyslog                   # 查看rsyslog状态
logger -p local0.info "test message"# 发送测试日志
logger -t myapp "tagged message"# 带标签的测试日志

# === journalctl相关 ===
journalctl -u nginx.service               # 查看指定服务日志
journalctl -f                             # 实时跟踪日志
journalctl -p err                         # 只看错误及以上
journalctl --since "1 hour ago"# 最近1小时日志
journalctl --since "2024-01-15 10:00"# 指定时间起
journalctl -b -1                          # 上次启动的日志
journalctl --disk-usage                   # 查看日志占用空间
journalctl --vacuum-size=500M             # 清理日志到500M以内
journalctl --vacuum-time=7d               # 清理7天前的日志
journalctl -o json-pretty -n 5            # JSON格式输出最近5条
journalctl --list-boots                   # 列出所有启动记录
journalctl _PID=1234                      # 按PID查看
journalctl _EXE=/usr/sbin/sshd           # 按可执行文件查看

# === logrotate相关 ===
logrotate -d /etc/logrotate.d/nginx       # 调试模式(不实际执行)
logrotate -f /etc/logrotate.d/nginx       # 强制执行轮转
logrotate -v /etc/logrotate.conf          # 详细模式执行
cat /var/lib/logrotate/logrotate.status   # 查看轮转状态

# === 日志文件操作 ===
tail -f /var/log/messages                 # 实时查看系统日志
tail -f /var/log/secure                   # 实时查看认证日志
> /var/log/xxx.log                        # 清空日志文件(不删除)
truncate -s 0 /var/log/xxx.log            # 清空日志文件
du -sh /var/log/*                         # 查看各日志文件大小
lsof | grep deleted                       # 查找已删除但未释放的文件

B. 配置参数详解

rsyslog主要配置参数

参数
位置
默认值
说明
workDirectory
global
/var/lib/rsyslog
工作目录,队列文件存放位置
maxMessageSize
global
8k
单条日志最大大小,超过会截断
preserveFQDN
global
off
是否保留完整域名
queue.type
action
Direct
队列类型:Direct/LinkedList/FixedArray/Disk
queue.size
action
1000
内存队列最大条目数
queue.maxDiskSpace
action
无限制
磁盘队列最大空间
queue.saveOnShutdown
action
off
关闭时是否保存队列到磁盘
queue.workerThreads
action
1
工作线程数
queue.dequeueBatchSize
action
16
批量出队大小
action.resumeRetryCount
action
0
重试次数,-1为无限重试
action.resumeInterval
action
30
重试间隔(秒)
asyncWriting
omfile
off
异步写入
flushInterval
omfile
1
flush间隔(秒)
ioBufferSize
omfile
4k
IO缓冲区大小
dynaFileCacheSize
omfile
10
动态文件名缓存大小

journald主要配置参数

参数
默认值
说明
Storage
auto
存储方式:persistent/volatile/auto/none
Compress
yes
是否压缩存储
SystemMaxUse
10%分区空间
持久化日志最大占用空间
SystemMaxFileSize
SystemMaxUse/8
单个日志文件最大大小
RuntimeMaxUse
10%内存
内存日志最大占用
MaxRetentionSec
0(不限制)
日志最大保留时间
MaxFileSec
1month
单个文件最大时间跨度
ForwardToSyslog
yes
是否转发到rsyslog
RateLimitIntervalSec
30s
速率限制时间窗口
RateLimitBurst
10000
时间窗口内最大条目数

logrotate主要配置指令

指令
说明
daily/weekly/monthly
轮转周期
rotate N
保留N份历史日志
compress
压缩历史日志(gzip)
delaycompress
延迟一个周期再压缩
dateext
用日期作为轮转文件后缀
dateformat
日期后缀格式
maxsize SIZE
超过指定大小就轮转
minsize SIZE
小于指定大小不轮转
missingok
日志文件不存在不报错
notifempty
空文件不轮转
create MODE OWNER GROUP
轮转后创建新文件
copytruncate
复制后清空原文件
sharedscripts
多个文件共享postrotate脚本
postrotate/endscript
轮转后执行的脚本
prerotate/endscript
轮转前执行的脚本
su USER GROUP
以指定用户执行轮转

C. 术语表

术语
英文
解释
设施
Facility
rsyslog中标识日志来源的分类,如kern、auth、cron、local0-7等,共24个
严重级别
Severity
rsyslog中标识日志严重程度的级别,从emerg(0)到debug(7)共8级
日志轮转
Log Rotation
定期将当前日志文件归档并创建新文件,防止单个文件无限增长
持久化存储
Persistent Storage
journald将日志写入磁盘(/var/log/journal/),重启后不丢失
易失性存储
Volatile Storage
journald将日志仅保存在内存中(/run/log/journal/),重启后丢失
队列
Queue
rsyslog中用于缓冲日志消息的机制,分内存队列和磁盘队列
规则集
Ruleset
rsyslog中一组过滤规则和动作的集合,可绑定到特定输入源
动态文件名
Dynamic File Name
rsyslog根据日志属性(如主机名)动态生成输出文件路径
RELP
Reliable Event Logging Protocol
可靠事件日志协议,保证日志传输不丢失
速率限制
Rate Limiting
限制单位时间内的日志条目数,防止日志风暴
文件描述符
File Descriptor
进程打开文件时获得的引用,日志轮转时需要注意fd的处理
脱敏
Desensitization
对日志中的敏感信息(手机号、身份证号等)进行掩码处理

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-02-09 02:06:33 HTTP/2.0 GET : https://f.mffb.com.cn/a/474402.html
  2. 运行时间 : 0.079210s [ 吞吐率:12.62req/s ] 内存消耗:4,892.11kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=1251d6c741171c8bf6b02124eca51408
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000627s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000934s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000313s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000296s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000475s ]
  6. SELECT * FROM `set` [ RunTime:0.000211s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000461s ]
  8. SELECT * FROM `article` WHERE `id` = 474402 LIMIT 1 [ RunTime:0.000740s ]
  9. UPDATE `article` SET `lasttime` = 1770573993 WHERE `id` = 474402 [ RunTime:0.008895s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000228s ]
  11. SELECT * FROM `article` WHERE `id` < 474402 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000376s ]
  12. SELECT * FROM `article` WHERE `id` > 474402 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000463s ]
  13. SELECT * FROM `article` WHERE `id` < 474402 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000638s ]
  14. SELECT * FROM `article` WHERE `id` < 474402 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.000571s ]
  15. SELECT * FROM `article` WHERE `id` < 474402 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000560s ]
0.080766s