做运维、做后端开发,谁都躲不开“查日志”这一步。而提到日志,syslog 这个词几乎绕不过去。它不是某一个软件,也不属于某一家厂商,而是一套从 Unix 时代就定下来的日志传输标准,被 Linux、网络交换机、路由器、防火墙、存储设备甚至不少嵌入式系统广泛支持。说白了,只要你想把分散在不同机器上的日志统一收起来,syslog 永远是那个最底层、最不挑设备的方案。
这篇文章我会从协议原理、客户端配置、服务端搭建、日志轮转,到实战排查一条线讲完。新手可以照着配置一遍,老手也能在“踩坑记录”里找到一些平时文档里不写的东西。内容偏实际操作,尽量不堆概念。
1. 什么是 Syslog:先搞清楚这个三十年的协议怎么还在用
1.1 Syslog 的工作原理与核心角色
syslog 本质上是一个“发日志”的协议,规定了一台设备怎么把日志消息通过网络发给另一台设备。它有两种角色:产生日志并发送的叫客户端,接收并存储的叫服务端。消息默认走 UDP 514 端口,也可以配置成 TCP 514,需要加密传输时可以用 TLS,端口通常是 6514。
你可能会问,UDP 发送日志不是会丢包吗?是的,UDP 不保证送达。但 syslog 从设计上就接受了这个事实——日志消息本身是冗余的、可容忍丢失的,重要的是轻量、快速、不阻塞业务。所以实际生产环境里,大多还是 UDP 为主。真要做到不丢日志,一般会选 TCP 模式,或者干脆在传输层前面加消息队列,但那就是另一个话题了。
它的工作流特别简单:
- 客户端设备上的程序(内核、服务、应用)产生一条日志消息
- 本机的 syslog 服务(比如 Linux 上的 rsyslog)接收消息,根据配置决定写到本地文件还是转发到远程
- 远程服务端收到后,再根据来源 IP、程序名、日志级别等条件,分类写入对应文件
整个过程不需要复杂的握手认证,消息到了就写,写完了就完事。这也是为什么它能在各种设备上存活这么多年——足够简单,几乎零成本接入。
1.2 Facility 与 Severity:日志的“身份标签”
在 syslog 消息里,有两个关键字段你一定要懂,一个叫 facility(日志设施),一个叫 severity(严重级别)。
Facility 表示这条日志是“谁产生的”,相当于来源分类。常见的值包括:
| Facility 值 | 关键字 | 含义 |
|---|---|---|
| 0 | kern | 内核消息 |
| 1 | user | 用户进程 |
| 3 | daemon | 各种守护进程 |
| 4 | auth | 认证/安全相关(旧) |
| 5 | syslog | syslog 自身 |
| 8 | cron | 定时任务 |
| 9 | authpriv | 认证/私密安全消息 |
| 16-23 | local0 - local7 | 用户自定义,常给应用或网络设备用 |
Severity 表示这条日志有多严重,从 0 到 7 依次递减:
| 级别值 | 关键字 | 含义 |
|---|---|---|
| 0 | emerg | 系统不可用,比如内核崩溃 |
| 1 | alert | 必须立即处理,比如磁盘满 |
| 2 | crit | 严重问题,硬件故障 |
| 3 | err | 错误,但不至于宕机 |
| 4 | warning | 警告,有潜在风险 |
| 5 | notice | 正常但值得关注 |
| 6 | info | 常规信息 |
| 7 | debug | 调试信息 |
这两个值组合在一起会算出一个 PRI 值,公式是facility * 8 + severity。比如 local0.info 的 PRI 就是 16 * 8 + 6 = 134。你在配置 rsyslog 过滤规则时,写的local0.info最终就是靠这个 PRI 值来匹配的,理解了它,之后看过滤规则就不会懵了。
2. 日志是怎么从设备里“跑”出来的:客户端配置实战
2.1 Linux 下开启 syslog 发送与测试
在 Linux 上,syslog 的实现最常见的是 rsyslog。它既是服务端也是客户端。要让它把日志转发到远程服务器,只需要在/etc/rsyslog.conf或者/etc/rsyslog.d/下的配置文件里加一行转发规则。
比如我想把所有日志都发给日志服务器 192.168.1.100,就加一行:
*.* @192.168.1.100:514注意这个@是 UDP 的意思,如果是两个@@就是 TCP。*.*表示所有 facility 的所有级别,也可以精确匹配,比如authpriv.*只发认证日志,*.info只发 info 以上级别的日志。
改完配置别忘了重启服务:
systemctl restart rsyslog重启后怎么验证有没有发出去?用logger命令手动发一条测试日志:
logger -p local0.info "this is a test log from linux client"-p指定 facility 和级别。这条日志会在本机写一份,同时按规则转发到远程。如果你在远程服务器上tail -f对应的日志文件,能看到这条消息,就说明链路通了。
这里有个细节建议:如果日志服务器收不到消息,先抓包确认有没有 UDP 包到 514 端口:
tcpdump -i eth0 udp port 514 -nn看到IP 192.168.1.10.xxxxx > 192.168.1.100.514这样的输出,说明客户端发出去了,问题多半在服务端。如果连包都没有,就得回头查防火墙和配置了。这一步能帮你快速缩小排查范围,比瞎猜有效得多。
2.2 Windows 设备和网络设备怎么接入
生产环境里不是只有 Linux 服务器,Windows 服务器和网络设备同样需要纳入日志体系,它们接入 syslog 的方式略有不同。
Windows 本身没有原生的 syslog 客户端,事件日志是写到系统自己的 Event Log 里的。想把它转发出去,常见方案是装第三方工具,比如 NXLog、Winlogbeat,它们会监听 Windows 事件,转换成 syslog 格式发到远程。以 NXLog 为例,核心配置大概是:
<Input eventlog> Module im_msvistalog SavePos true ReadFromLast true </Input> <Output syslog> Module om_udp Host 192.168.1.100 Port 514 Exec to_syslog_ietf(); </Output> <Route 1> Path eventlog => syslog </Route>这样 Windows 的应用程序日志、安全日志就能源源不断进入你的 syslog 服务端了。热搜词里那个“visual syslog server 下载”,其实是 Windows 上一个小工具,适合临时测试看日志推送,不适合大规模生产环境。生产环境还是建议用真的服务端。
网络设备(交换机、路由器、防火墙)一般都在 Web 管理界面或者命令行里有 logging 配置。以思科和华为为例,核心就是一条命令指向日志服务器:
logging host 192.168.1.100有些设备默认用 UDP 514,有些也可以指定端口和 facility,比如logging facility local0。配置完成后,设备的所有安全事件、接口状态变化、配置变更记录,都会往日志服务器发。这一步在等保、审计场景里几乎是必做的。
2.3 日志格式怎么读:一条日志拆开看
不管是什么设备发过来的日志,格式上都遵循两个主流标准:老的 RFC 3164,新的 RFC 5424。实际运维里 3164 更常见,很多设备到现在还是这个格式。
一条典型的 RFC 3164 日志长这样:
<134>Jun 22 10:30:25 web-server-01 sshd[12345]: Failed password for root from 203.0.113.10 port 22拆开看:
<134>:PRI 值,134 对应 facility 16(local0) + severity 6(info)Jun 22 10:30:25:时间戳,注意它没有年份,跨年排查时会踩坑web-server-01:主机名sshd[12345]:产生日志的程序名和进程 PID- 冒号后面:具体的日志内容
理解了格式,你才能写对解析规则。比如在 rsyslog 里按来源和程序分类,就是提取这些字段来做的。很多日志分析平台解析不出来日志,往往就是卡在 PRI 值的识别上。格式不乱、解析就对了一半。
3. 搭建集中式日志接收端:从 rsyslog 到开源日志服务器
3.1 用 rsyslog 快速部署一个 syslog 服务端
服务端的核心任务就两个:接收日志、按规则落盘。用 rsyslog 实现是最省事的,因为大多数 Linux 发行版都自带。
首先确认服务端加载了接收模块。编辑/etc/rsyslog.conf,把这两行取消注释:
module(load="imudp") input(type="imudp" port="514") module(load="imtcp") input(type="imtcp" port="514")有些老版本 rsyslog 的写法是$ModLoad imudp、$UDPServerRun 514,两种方式都行,看版本。改完后重启 rsyslog,用ss -lun | grep 514确认端口在监听。
只接收还不够,最实用的功能是按来源 IP 或者 hostname 自动分目录存。rsyslog 的模板功能可以做到:
$template RemoteLogs,"/var/log/syslog/%FROMHOST-IP%/%PROGRAMNAME%.log" *.* ?RemoteLogs这样每台设备的日志会按设备 IP 和程序名分开存,查找非常方便。否则所有日志堆在一个文件里,几百台设备时根本没法用。
生产环境里我建议同时监听 UDP 和 TCP,原因很简单:UDP 兼容大多数老旧设备,TCP 给重要的服务器用,保证关键日志不丢。两边都开着,覆盖面最好。
3.2 开源 syslog 日志服务器怎么选:Visual Syslog Server、Graylog、Loki
rsyslog 配置虽然灵活,但检索能力基本为零。日志多了以后,你会需要能搜索、过滤、可视化的工具。这里说几个我实际用过的开源方案。
Visual Syslog Server是一个轻量的 Windows 程序,打开就能看到由日志流,界面简单,适合临时测试、开发联调,也适合刚入门的人理解 syslog 长什么样。但它的存储和查询能力很弱,生产环境坚持不了多久。你能在网上找到它下载,但别指望靠它做长期归档。
Graylog是真正能承担生产角色的开源方案。它把 syslog 消息接收下来后,经过解析、提取字段,存入 Elasticsearch 里,查询响应非常快。优点是部署架构清晰、自带 Web 界面、权限管理完整、告警规则配置方便。缺点是组件多(Graylog + MongoDB + Elasticsearch),吃内存,想跑得舒服至少 8G 起步。适合日志量在百万条/天以上、有集中查询需求的场景。对应热搜词“开源 syslog 日志服务器”,Graylog 是值得优先试的一个。
Loki是 Grafana 出的日志系统,定位跟 ELK 不一样。它以标签索引为主,不建立全量文本索引,所以资源占用比 ELK 低很多,查询语法也更贴近 grep。适合已经用 Grafana 做监控看板的团队,顺手把日志也接进来,一套界面管指标和日志。缺点是复杂字段提取能力相对弱,不像 Graylog 那样有完善的 Extraction Pipeline。
选型建议很简单:服务器少、要求不高,rsyslog 本地存就够了;Windows 小环境测试用 Visual Syslog Server;日志量大、需要搜索和告警,上 Graylog;团队技术栈在 Grafana 这边,用 Loki。别一上来就堆 ELK,资源和运维成本都很高,最后往往撑不住。
3.3 按设备分类存储与远程转发的注意事项
搭建好服务端,还有一个容易被忽略的点:日志怎么存、存多久。
日志存储要有明确的目录规划。我常用的结构是按 IP 和设备类型划分,比如:
/var/log/syslog/ ├── 192.168.1.10/ │ ├── sshd.log │ ├── nginx.log │ └── su.log ├── 192.168.1.20/ │ ├── kernel.log │ └── app.log └── 192.168.2.1/ ├── interface.log └── security.log路径清晰,后续不管是给审计还是排查问题,都能快速定位。如果只存一个messages.log,后果就是你会在一个几 GB 的文件里 grep 到怀疑人生。
数据保留周期要提前想好。安全审计通常要求日志留存至少 180 天;业务日志可以短一些,30 天比较常见。这个周期直接影响磁盘规划,所以建议一开始就估算好日志增长速度,再做裁剪策略。
另外一点,如果公司已经有集中日志系统(比如 Kafka + ES),rsyslog 可以只做中转,不落盘。配置上把日志同时转发给下一级服务就行:
*.* @192.168.1.200:514这样本机不存、不占空间,纯粹当管道用,能减轻服务端压力。要不要在中转层落盘,取决于你对外提供的合规要求,不强制。
4. 日志文件的管理与轮转:logrotate 解决磁盘写满问题
4.1 为什么日志会“吃掉”磁盘:logrotate 的执行机制
日志只要在跑,就会不停增长。一个高频应用一天写几个 GB 日志毫不夸张,如果没人清理,磁盘被写满只是时间问题。磁盘写满后,服务可能直接崩溃,带来的损失比“丢日志”严重得多。这时候就需要 logrotate 出马。
logrotate 本身就是 Linux 上用来做日志轮转的标准工具。它的核心机制很简单:按时间周期或文件大小触发,把旧日志改名压缩,保留指定份数,超出部分自动删除。它通过 cron 定时任务每天执行,默认路径是/etc/cron.daily/logrotate,所以即使你不配置任何东西,系统自带的日志(比如/var/log/messages)也会被轮转。
它的执行流程是这样的:
- cron 触发
/usr/sbin/logrotate /etc/logrotate.conf - logrotate 读取
/etc/logrotate.d/下的各应用配置 - 对每个日志文件检查是否满足轮转条件
- 满足条件就执行 rename、压缩、通知应用重新打开日志文件
- 删除超过保留份数的旧文件
理解了这个流程,你就能自己控制轮转的频率和保留数量,不再被动等磁盘报警。
4.2 实战配置 logrotate:从系统日志到应用日志
来看一个实际配置,管理系统自带日志:
/var/log/messages { weekly rotate 4 compress delaycompress missingok notifempty }解释一下关键项:
weekly:每周轮转一次rotate 4:保留 4 份归档,也就是留一个月的日志compress:对归档文件 gzip 压缩delaycompress:延迟压缩,最近一次归档不压缩,方便立即排查missingok:日志文件不存在时不报错notifempty:文件为空时不轮转
应用日志更常见的是按大小轮转。比如一个 Java 应用,每天日志量不定,按天数轮转容易在高峰期一天写几个 GB,我一般用 size 做触发条件:
/app/logs/springboot-app.log { daily size 500M rotate 15 compress dateext dateformat -%Y%m%d copytruncate missingok }这里说下copytruncate:它先复制文件内容到归档文件,然后清空原文件。缺点是复制和清空之间可能丢少量日志,但优点是应用进程不需要重启,也不用重新打开文件句柄。对无法响应 SIGHUP 的 Java 应用来说,这是最省事的方案。如果你的应用能重新打开日志文件,建议用默认方式而不是 copytruncate,日志完整性更高。
配置完可以用logrotate -d做调试,用logrotate -f强制轮转:
logrotate -d /etc/logrotate.d/springboot logrotate -f /etc/logrotate.d/springboot-d不会真正执行,会打印详细过程,用于检查语法和条件判断;-f强制执行,无论是否到达轮转周期。先-d后-f,是标准操作顺序。
4.3 Spring Boot 应用日志保留三个月:两种实现思路
热搜词里有个很具体的问题:“springboot 项目部署后日志只保留三个月”。这个需求其实两个层面都能实现。
第一层是用系统层的 logrotate 管。只要日志是写文件而且按天滚动,logrotate 用rotate 90+daily就能保留三个月。配置参考上一节的 size 版本就行。
第二层是应用自身管。Spring Boot 用的日志框架是 Logback,logback 自带滚动和清理策略。在logback-spring.xml里这样配:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>/app/logs/springboot-app.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>/app/logs/springboot-app.%d{yyyy-MM-dd}.log.gz</fileNamePattern> <maxHistory>90</maxHistory> </rollingPolicy> </appender>maxHistory是保留多少天的日志文件,超过自动删除。90 就是三个月。注意文件名里带.gz会自动压缩,省磁盘空间。两套方案选一个就行,我倾向用应用层配置,因为不依赖服务器上的 logrotate 配置是否到位,迁移环境时更容易保持一致性。但是 logrotate 方案的好处是统一管理,适合应用到日志目录固定的场景,两个都试过之后,最终我自己的环境是应用层负责生成和清理,系统层只兜底。
还要提醒一句,上面说的清理机制只适用于应用自己滚动出的文件。如果你的应用一直往同一个文件写,但是没有触发滚动,logrotate 的copytruncate反而更可靠。这一点在排查“日志文件越来越大但是就是没被删掉”这种问题时,往往是关键。
有一个容易忽略的点:Logback 的maxHistory只在滚动发生时去检查并删除过期文件。也就是说,如果应用长时间不产生日志、不触发滚动,旧文件不会被清理。遇到这种“日志堆积但没滚动”的情况,可以手动把app.log改个名触发一次滚动,或者加一个定时任务兜底。类似的坑在 binlog 身上也有——很多 MySQL 实例的 binlog 不是删不掉,而是没到expire_logs_days的计算条件,这个在排查时也值得一并想到。
5. 日志分析实战:从登录审计到故障定位
5.1 登录日志分析:谁在什么时候登录了系统
安全审计里最常查的就是登录日志。Linux 下登录日志在auth.log(Debian/Ubuntu)或者secure(CentOS/RHEL)里,通过 syslog 集中收集后,可以跨多台机器统一查。
想看成功登录的记录:
grep "Accepted password" /var/log/syslog/192.168.1.10/sshd.log输出里会有时间、用户名、来源 IP:
Jun 22 10:30:25 web-server-01 sshd[12345]: Accepted password for root from 203.0.113.10 port 22 ssh2想看暴力破解的失败尝试,统计每个 IP 试了多少次:
grep "Failed password" /var/log/syslog/192.168.1.10/sshd.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn这里$(NF-3)取的是来源 IP 字段。单机这样过滤没问题,跨机器分析还是要丢进 Graylog 或者用脚本汇总,不然操作成本太高。
有一个细节值得注意:Accepted password和Accepted publickey要分开统计,因为公钥登录通常可以视为合法自动化运维行为,而密码登录才是需要重点盯的对象。如果某台机器平时从来不用密码登录,却突然出现大量密码验证成功的记录,那基本可以断定弱口令被扫到了,这时候要立即处理,而不是只记个日志。
5.2 查关机与重启日志:系统什么时候掉过线
排查系统异常时,经常需要知道系统上次是什么时候关的机、什么时候重启的。这直接关系到判断问题是硬件挂掉、内核崩溃还是有人误操作关机。
Linux 下最常用的命令是last:
last reboot它会列出所有重启记录,带时间戳,一眼就能看出最近有没有异常重启。想看更久远的历史,可以查/var/log/wtmp。登录相关的历史记录在/var/log/btmp和/var/log/wtmp,它们未必走 syslog,但 rsyslog 的配置里通常也会引用到这些基础日志。当 wtmp 文件被清理,而 syslog 里的kernel.log和shutdown.log还在时,你依然能从远程集中日志里找回重启痕迹——这就是日志集中收集的优势之一。
在 systemd 系统上,journalctl更强大:
journalctl --list-boots journalctl -b -1 -e--list-boots会列出历史上每次启动的记录 ID 和时间,-b -1表示查看上一次启动的日志,-e跳到尾部。如果上次系统异常,这次启动后进journalctl -b -1往往能看到内核 panic 或 OOM 的线索。要注意,journald 默认日志可能因容器部署不持久化,重启后丢失。所以重要系统的 journald 日志建议配置持久化,或者全部汇入 syslog 集中平台,否则重启原因永远查不清。
5.3 从 syslog 延伸到各类日志的关联排查
实际运维中,报障经常不是单看一种日志就能定位的。系统日志说磁盘满了,但你得知道是什么文件涨的;应用日志说数据库连接超时,你得去翻慢查询日志,看看是不是 SQL 有问题;容器环境更麻烦,一个 pod 崩溃,系统日志、容器日志、应用日志、k8s event 全都要串起来看。
syslog 在这个链条里的角色是“底层地基”。内核报错、OOM、网络断开、硬件异常,这类信息只有 syslog 里的kern.*会记录,应用层往往感知不到。比如数据库连接突然全断,先查/var/log/messages里有没有网络接口 down 的记录,很可能根源就是网卡瞬断,跟数据库自身没关系。
至于应用代码产生的日志,一般建议直接落在独立的日志文件或容器 stdout 里,再通过 Filebeat 或 Promtail 接入 Loki、ELK。不必强行塞进 syslog,因为应用日志量大、格式复杂,syslog 的 UDP 传输和纯文本格式不够用。但 syslog 作为“最后一根救命稻草”,在应用完全起不来、文件日志也没写出来的极端情况下,往往只有它留了现场。所以我的习惯是:重要的生产服务器,系统级别日志永远发一份到远程 syslog,不管有没有上日志平台。
还有 MySQL 的 binlog 这类二进制日志,跟 syslog 更不是一回事,但排查数据恢复时经常要一起看。binlog 能不能删,什么时候删,取决于备份策略和数据恢复窗口,而不是 “看着脏就删”。这里只是提一句:日志文件分很多种,syslog 管的是“运行状态”,binlog 管的是“数据变更”,两者别混着处理。
6. 常见问题与排查经验:我在 syslog 上踩过的坑
6.1 日志收不到,先按这个顺序查
问题一出现,很多人会先怀疑网络,其实大部分时候是配置问题。我整理过一个排查顺序,照着走基本能定位 80% 的问题:
- 客户端有没有发出包:先
tcpdump -i any udp port 514 -nn,如果没包,看客户端防火墙是否放行、rsyslog 配置有没有生效、服务有没有重启。 - 服务端有没有收包:同样抓包,如果收到但写不了文件,看服务端防火墙是否没放行(比如只有 TCP 放行),或者 SELinux 阻止了 rsyslog 写入目录。
- 落盘权限:rsyslog 以什么用户跑,模板指向的目录权限能否让它写入。如果目录不存在,日志直接丢弃。这是刚搭建时最高频的踩坑点。
典型案例:服务端日志模板写的目录是/var/log/syslog/192.168.1.10/,但这个目录没有提前创建,rsyslog 不会自动建目录,结果日志全丢,抓包却能看到包已经到了。解决方法是提前mkdir -p,或者用模板里带!的语法让 rsyslog 自动建目录。
6.2 时间戳对不上:比日志内容更坑的是日志时间
排查线上问题时,时间不统一会造成巨大干扰。客户端本地时间快了两分钟,服务端按自己时间记录了接收时间,两条日志一对,顺序就对不上。更要命的是,像网络设备这种老旧设备可能连 NTP 都没配,日志时间跟真实时间差着好几个小时。
强烈建议所有机器开启 NTP 同步:
timedatectl set-ntp true同时检查时区:
timedatectl如果服务端和客户端在不同时区,建议日志统一记录为 UTC,查看时再转换,这样可以避免夏令时、时区切换造成的错乱。我经历过一次凌晨两点日志时间“回流一小时”的线上事故,就是因为当时用本地时间做日志归档和告警判断,时区切换导致告警直接停顿。从那以后,凡是进日志系统的设备,时间策略统一先定下来,这是基础设施级别的注意事项。
6.3 日志文件暴涨与审计日志留存
日志暴涨除了应用 bug,很多时候是配置不当造成的。比如*.*把 debug 级日志全发上来了,比如某个程序的异常日志刷屏每秒几百条。服务器一多,几分钟就能写满磁盘。
我处理过最夸张的一次,一台 NTP 服务端配置错误,客户端疯狂请求,导致每个分钟都有日志,一个 100G 的分区一个晚上就满。排查办法还是先看落盘量:
du -sh /var/log/syslog/*找到源后,用 rsyslog 的过滤规则把高频噪音丢弃:
if ($programname == "ntpd") then { stop }stop表示不再继续处理这条日志。业务上高频刷屏的日志,尽量在源头控制频率,比在服务端丢日志更健康。应用里该打日志的地方要打,但无意义的循环、探活日志可以降级为 debug,线上不要开 debug 写入。
另外,审计类日志的留存可能涉及合规要求(比如要求 180 天),日志量又大,这时要尽早做归档策略:热数据在 ES,冷数据压缩后存对象存储,同时做校验和记录,防止被篡改。日志留存不只是一个存储问题,它和审计审查直接挂钩,别等被检查时才想起来补,到时候数据早被轮转删光了。
6.4 一次线上实例:用 syslog 定位容器应用的偶发崩溃
去年我这边有个 Java 服务,运行在 Docker 容器里,经常凌晨两三点挂掉,应用日志里最后一条记录是某个请求超时,没有报错堆栈。常规排查完全无从下手。
后来想到查宿主机日志。打开 rsyslog 收到的/var/log/messages,果然发现了端倪:容器挂掉的时间点,内核有一条 OOM 记录,正是那个 Java 进程的 PID 被系统杀掉了。再配合journalctl -t kernel看完整 OOM killer 输出,发现是宿主机内存不够,把容器进程杀了。
如果当时没有配 syslog 远程日志,这台服务器重启后,journald 的本地所有记录都会丢失,OOM 证据就完全没了。最后我们解决了问题:给该进程设置 JVM 堆内存上限,并在启动参数里加上-XX:+ExitOnOutOfMemoryError,避免被系统误杀之后出现僵尸进程还继续写日志。其实这个方案不算复杂,但是没有日志就没有方向。
这个案例我提过很多次,因为它是典型的“应用日志给不了答案时,syslog 补上了关键拼图”的场景。
6.5 日志轮转不生效的常见原因
最后总结几个 logrotate 的“隐形杀手”。
一是配置文件权限。logrotate 要求配置文件不能被组写、其他人写,权限要是 644 或更严格,否则直接提示“ignoring configuration file ... because of bad file permissions”,配置完全不执行。这个报错很隐蔽,我第一次遇到时排查了很久。二是cron 没跑。如果/etc/cron.daily所在的服务被禁用,logrotate 就永远不触发。三是拷贝截断丢日志。用了copytruncate,应用写入量大的时候可能日志文件正在写,复制文件内容时只复制了前半段,应用还没写到的内容就留在了原文件里,清空后这一部分就丢了。有强审计要求的系统建议用create模式让应用重新打开文件,但前提是应用支持 signal 重开日志文件。
排查 logrotate 是否按要求轮转,执行手动模式并打印状态,最直接:
logrotate -vf /etc/logrotate.d/your-config一旦日志文件开始轮转并压缩,就说明链路通了。
真正把 syslog 用起来之后,它不会给你任何“秒级告警”的惊喜,也不会帮你做花哨的图表。它更像是一个沉默的底座,把每台机器的运行状态一五一十记下来,平时你可能想不起它,但真到需要的时候,它记录的那几行字往往比任何监控面板都诚实。这也是我一直坚持把系统日志集中收起来的原因——不是每个问题都能靠监控指标提前发现的,更多时候,答案就在日志里,看你能不能找到它。