ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux日志管理实战:logrotate轮转与rsyslog/Filebeat集中收集

Linux日志管理实战:logrotate轮转与rsyslog/Filebeat集中收集 接手过几台服务器之后你就会发现日志这东西平时没人关心一出事所有人都盯着你。日志管理这个活儿听起来不起眼做不好真的会出事故磁盘被日志写满导致服务挂掉、排查问题时发现关键日志已经被轮转清掉、线上几十台机器要逐个登录进去翻日志……这些问题我全踩过。这篇文章就围绕Linux日志管理这条主线从单机上的logrotate轮转讲起再到用rsyslog和Filebeat做集中收集最后把分析时常用的命令和踩坑经验一起整理出来。适合刚接触Linux运维的读者也适合已经在做基础运维、想把自己的日志体系做得更规范的朋友。1. 日志管理这件事为什么越早做越省心1.1 日志不只是用来排错的很多人把日志简单理解成“报错记录”其实日志的价值远不止这些。系统日志、应用日志、访问日志、审计日志本质上是一台服务器在某个时间点上的“行为快照”。你可以把它当成飞机的黑匣子正常情况下没人关注它但一旦出问题它就是你还原现场的唯一依据。我见过不少刚做运维的同事对日志的态度是“能跑就行反正没报错”。结果真到线上出故障的时候连最基本的“服务是什么时候开始异常的”都答不上来。反过来日志管理做得好的团队故障定位往往只要几分钟先看时间窗口再看关键字再用统计命令确认影响范围最后才动手处理。这套流程的前提就是日志体系本身是可靠的、完整的、可检索的。Linux系统里日志分布其实很零散/var/log/messages、/var/log/syslog、/var/log/auth.log、/var/log/nginx/access.log加上systemd的journald日志以及各种应用自己写的日志文件。如果不做统一规划排查问题时你得在不同目录、不同文件名、不同格式之间来回跳。所以第一步不是急着写分析脚本而是先把“日志到底存在哪、保留多久、怎么轮转”这个基础问题想清楚。1.2 不管理日志会出哪些事先列几个我真实遇到过的场景。第一个是磁盘写满。曾经有一台业务服务器的根分区只有40G某个Java应用因为配置不当把DEBUG日志无条件输出三天就把磁盘写满了。数据库直接报“No space left on device”业务全挂。这种事故的元凶不是业务代码而是日志没人管。第二个是日志被轮转清掉了。默认的logrotate可能只保留4周等你接到告警、登录服务器去查的时候关键时间段的日志已经没了。第三个更常见服务器一多你根本不知道问题日志在哪台机器上。所以说一套靠谱的日志体系至少要解决四件事轮转让日志文件大小可控保留策略让历史日志既有价值又不占空间集中收集让多台机器的日志能在一个地方看分析能力让日志真正能被快速检索和统计。这四个环节是递进的单机先做好轮转再谈集中收集否则一堆机器每天往中心节点狂推日志收下来也没人看。Linux系统里常见的日志类型和位置我整理了一张表方便新手对照日志类型常见路径主要记录内容系统日志/var/log/messages 或 /var/log/syslog内核信息、系统服务运行信息认证日志/var/log/auth.log 或 /var/log/secure登录、sudo、认证相关事件内核日志/var/log/dmesg、journald硬件、驱动、内核消息应用日志/var/log/nginx/、/var/log/mysql/ 等应用自身输出定时任务日志/var/log/croncrontab执行情况2. logrotate轮转把日志“养”在可控范围内2.1 轮转的核心逻辑与关键配置项logrotate是Linux下最经典的日志轮转工具。它的核心机制并不复杂在约定的时间点把当前正在写入的日志文件重命名或复制然后通知应用重新打开日志文件同时保留最近若干个历史文件通常还会做压缩。这个过程如果设计不好最常见的坑就是“服务还在写旧文件句柄”导致轮转之后日志继续往被重命名的文件里写新文件反而一直空着。先说logrotate的几个关键配置项理解了它们配置就不会出错。rotate N保留N份轮转后的历史日志超过就删除最旧的。daily / weekly / monthly执行轮转的周期。maxsize当日志文件达到这个大小就立即轮转不管周期是否到了size只有文件超过这个大小才轮转。compress轮转后对历史日志做gzip压缩delaycompress延迟一次轮转再压缩因为有些应用在重命名后还会向旧文件写一段时间的日志。copytruncate先复制当前日志到历史文件再把原文件清空。这种方式不需要应用重开文件句柄适合没法通过信号通知的应用。dateext轮转后的文件名带上日期避免同一天重复轮转把文件覆盖掉。missingok日志文件不存在时不报错。notifempty文件为空时不轮转。postrotate / endscript轮转后执行的命令通常是让应用重新打开日志句柄。sharedscripts多个日志配置匹配同一个模式时脚本只执行一次避免重复通知。你需要根据应用类型选择策略。像Nginx、Apache这类支持信号重开的服务用rename postrotate里发USR1信号的方式比较干净像一些自己写日志的Java应用没捕获信号逻辑就用copytruncate虽然会丢失极少量的日志复制和截断之间存在微小窗口但胜在安全。2.2 一份可以直接抄的logrotate配置我自己在服务器上用的配置风格比较统一所有应用日志都放在/etc/logrotate.d/下面单独建文件。下面是一份处理Nginx日志的配置可以直接参考/var/log/nginx/*.log { daily rotate 14 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 }这里解释几个关键点。daily rotate 14意味着保留14天如果你觉得太多7天也够关键看你的磁盘和合规要求。dateext加dateformat可以避免文件名重复Nginx日志的access.log会在轮转后变成access.log-20250612这种格式后期想按天拉取或统计非常方便。sharedscripts配合通配符路径确保所有匹配的文件轮转完之后只执行一次Nginx重开信号避免每个文件都发一次USR1造成无谓开销。delaycompress是个细节Nginx在rename之后旧句柄可能还会短暂写入一些日志延迟一轮压缩能保住这部分数据避免解压一堆半截文件。再给一个Java应用日志的配置场景。很多Java服务在logback里配置了滚动但如果你在系统层面也要保留一份轮转建议用copytruncate并且把Java应用自己的滚动频率调低避免两种机制打架/opt/myapp/logs/*.log { daily rotate 7 compress copytruncate missingok notifempty }只要记住Java进程本身不知道文件被替换了所以copytruncate是最省心的方式。2.3 轮转测试与手工触发配置写完一定要测不要直接丢到生产环境。logrotate自带调试模式logrotate -d /etc/logrotate.conf-d是debug只打印执行过程不真正操作文件。它会告诉你配置文件有没有语法错误、哪些文件会被轮转、会执行什么命令。确认没问题之后可以手工触发一次logrotate -f -v /etc/logrotate.d/nginx-f是强制轮转-v是输出详细信息。你会发现它创建了历史文件、执行了postrotate脚本然后可以立即检查Nginx日志是否还在正常写入。这一步非常重要我见过很多人在测试环境加了-f反复跑结果状态文件错乱第二天正式轮转时反而“跳过”。所以强制轮转只用于验证别在线上频繁操作。logrotate本身靠cron或systemd timer触发。大多数发行版默认在/etc/cron.daily/里放了logrotate脚本所以鹿奇注意一下你的系统是不是真的每天定时执行了。检查方法很简单cat /etc/cron.daily/logrotate systemctl list-timers | grep logrotate如果在容器里或自定义环境里没有这个定时任务就需要自己加一条crontab。很多“日志不轮转”的问题根因就是cron服务挂了或者日志残留太大了。3. 日志分析三板斧grep、awk与时间窗口思维3.1 从一堆日志里快速定位问题日志分析最常用的工具其实不是那些高大上的平台而是grep、awk这种基础命令。我常说分析日志的80%工作是在“过滤”把几万行日志缩小到几百行甚至几十行剩下的就靠人眼判断。先看grep。普通搜索就不说了关键是熟练使用扩展正则和上下文参数grep -E ERROR|Exception|OutOfMemory app.log grep -E 2025-06-12 1[0-9]: app.log | grep -v 健康检查 grep -C 5 NullPointerException app.log-C 5表示打印匹配行的前后5行这对排查异常堆栈非常有用。如果你面对的是已经压缩的历史日志先把grep替换成zgrep就行zcat也可以直接看内容zgrep -E OutOfMemory app.log-20250612.gz接着是tail。我排查问题时的标准动作是先开一个tail窗口盯着最新日志再去翻历史。tail -F会自动重试打开被轮转替换的文件这个特性在日志轮转场景下比tail -f靠谱得多tail -F /var/log/nginx/error.log如果用的是systemd管理的服务journalctl也是重点工具。按时间过滤、按单元过滤、按关键字过滤都能一条命令完成journalctl -u nginx --since 2025-06-12 10:00:00 --until 2025-06-12 11:00:00 journalctl -k | grep -i sd3.2 统计类分析与实用技巧过滤只能定位线索真要评估影响范围就得靠统计。awk是这里的主角。我拿最常见的Nginx access.log举几个例子。统计访问量Top 10的IPawk {print $1} access.log | sort | uniq -c | sort -rn | head -10统计HTTP状态码分布awk {print $9} access.log | sort | uniq -c | sort -rn统计某段时间内的请求总量和流量awk $4 [12/Jun/2025:10:00:00 $4 [12/Jun/2025:11:00:00 {bytes $10; count} END {print count, bytes}awk处理日志本质上就是按空格或自定义分隔符把每一行拆成字段然后取你要的字段做累加、分组。字段序号取决于日志格式建议先用head -1看一下实际格式确认第几列是状态码、第几列是响应字节数再写awk否则统计结果完全不对。除了统计日志分析里还有一个核心思维时间窗口。我排查问题从来不从头翻到尾而是先通过监控或业务反馈确定一个大概的时间段再用grep或awk把时间窗口里的日志单独抠出来。比如用sed取文件的某个时间区间sed -n /2025-06-12 10:05:00/,/2025-06-12 10:15:00/p app.log这比直接在全量日志里找异常要快得多。我建议新手养成一个习惯拿到日志先看文件大小和时间跨度再决定用哪种方式过滤。日志本身是时间序列数据所有分析都应当先限定时间范围再缩小关键字范围效率会高出一个量级。我把常用分析任务和对应命令整理成了表格分析目标推荐命令找关键字上下文grep -C 5统计访问量Top IPawk sort uniq统计状态码分布awk sort uniq -c限定时间段提取日志sed -n /起始/,/结束/p实时监控新日志tail -F查看systemd服务日志journalctl -u 服务名 --since4. 集中收集从单机到集群的必经之路4.1 先搞清楚需求再选架构单机上日志管理做得再好服务器数量一多你还是会遇到一个尴尬问题出了问题不知道去哪台机器找日志。我经历过最痛苦的一次排查是五台Web服务器轮询负载线上报了一个偶发错误结果我五台机器挨个登录用grep遍搜索才定位到具体是哪台的日志有问题。从那时候起我就意识到集中收集不是可选项是必经之路。但集中收集不等于一上来就上ELK全家桶。架构选型要看规模和需求三五台机器只需要系统日志和关键应用日志归拢到一个节点用rsyslog完全够。几十台机器需要全文搜索、可视化、告警才考虑Filebeat加Elasticsearch这套。如果业务日志结构复杂还要做清洗、关联再引入Logstash或轻量级的处理管道。我的建议是先搞清楚“我要解决什么问题”再决定“用什么工具”。比如你只是希望登录一台机器就能看到所有服务器的/var/log/messagesrsyslog半小时就能搭好你想按关键字搜索历史全量日志那才需要索引系统。不要一开始就上一套重架构维护成本往往比收益还大。4.2 rsyslog集中收集轻量方案rsyslog是Linux内置的日志收集组件绝大多数发行版都预装了。它既能收系统日志也能收指定文件配置起来非常简单。我常用的部署模式是一台日志中心节点其他节点往这个节点的514端口发日志。中心节点配置修改/etc/rsyslog.conf开启UDP和TCP接收module(loadimudp) input(typeimudp port514) module(loadimtcp) input(typeimtcp port514)还需要定义模板把不同主机的日志存到不同目录避免所有机器日志混在一个文件里。比如这样$template RemoteLogs,/var/log/remote/%fromhost-ip%/%programname%.log *.* ?RemoteLogs然后在规则区加上这两行重启rsyslogsystemctl restart rsyslog客户端更简单只有一句把本地所有日志转发到中心节点*.* 192.168.1.10:514这里是UDP是TCP。UDP开销小但会丢日志TCP可靠但稍重。如果是系统日志这种对实时性要求不高的场景UDP就够了如果日志涉及审计、不能丢就选TCP。搭建过程中有几个点特别容易踩坑。SELinux默认会拦imtcp的514端口遇到收不到日志的情况先检查SELinux上下文再检查firewalld是否放行了514。另外时间同步一定要做所有机器用同一套NTP否则日志到了中心节点之后时间线是乱的根本无法排错。4.3 Filebeat Elasticsearch方案当需要检索和可视化的能力rsyslog就有些吃力了。我的经验是优先用Filebeat直接打到Elasticsearch省去Logstash那一层只要你不做复杂的日志清洗性能足够组件也少排障更容易。Filebeat实际上是一个日志采集代理它的核心工作是追踪文件变化把新增内容读出来发给后端的存储或检索系统。先看filebeat.yml里最核心的输入配置filebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/*.log fields: service: nginx fields_under_root: true output.elasticsearch: hosts: [http://192.168.1.20:9200] index: filebeat-%{yyyy.MM.dd}启动后Filebeat会自动记录每个日志文件读到哪个位置这个状态写在/var/lib/filebeat/registry文件里所以不要随便删registry否则会重复推送全量日志。Filebeat最大的好处是轻量、稳单机内存占用通常在100M以内配合Elasticsearch做搜索足够了。我见过很多团队一上来就三节点Elasticsearch加Logstash加Kafka最后真正用起来的只有“日志搜索”这一个功能。我的建议是从最小可用架构开始。单节点Elasticsearch加Filebeat足够支撑几十台机器的日志检索等流量上来了再横向扩展。对比一下rsyslog和Filebeat两套方案的适用场景维度rsyslog集中收集Filebeat Elasticsearch部署复杂度极低改配置即可中等需要维护ES适用规模几台到十几台几十台以上检索能力靠grep/zgrep全文索引、关键字搜索数据清洗难灵活可配pipeline资源占用几乎为零Filebeat轻量ES较重5. 常见问题与排查实录5.1 轮转导致日志丢失或服务不写日志这个问题的典型场景刚从logrotate配置成copytruncate改成rename时出现。某次轮转之后Nginx的access.log一直不增长而老的access.log-日期文件在持续变大。原因是Nginx进程还持有旧文件句柄postrotate脚本里发了USR1信号但应用没接管。解决方案是确认postrotate脚本有没有正确执行以及应用是否支持该信号。Nginx、Apache都没问题但有些自研服务是不支持的这时候要么用copytruncate要么在应用代码里实现对SIGHUP的信号处理。另外一个更隐蔽的问题logrotate根本就没跑。之前接手的服务器上/etc/cron.daily/logrotate文件权限异常导致不执行日志文件几个月没轮转。排查思路其实很简单先手动执行一次logrotate -d看流程再检查cron服务状态最后看/var/lib/logrotate.status里的state记录。我习惯在每台机器上把logrotate的执行结果写进/var/log/logrotate.log方法是在/etc/logrotate.conf里加logrotate --verbose 2 /var/log/logrotate.log5.2 时间、时区和格式的坑集中收集之后最头疼的就是日志时间不统一。先说NTP系统日志全部依赖本地时间如果服务器之间差了五分钟排错时间线看着就像错位的电影。建议所有服务器启用NTP同步并在日志格式里带上时区比如用2025-06-12T10:15:0008:00这种ISO8601格式避免UTC和本地时间混淆。journald默认显示的是本地时间但底层存储是UTC时间。如果你从journalctl导出日志然后和rsyslog收到的系统日志做对比会发现时间差了8小时。这不是bug是格式问题。解决方案是统一在日志处理阶段约定一个标准时区我一般约定所有节点都使用UTC存储、展示时再转本地时间。集中收集系统里时间口径不一致造成的“故障定位偏移”比日志丢失还致命因为你会根据错误的时间窗口去翻日志结果什么都找不到。5.3 集中收集中的网络与权限问题rsyslog中心节点收不到日志我总结了三个高频原因。第一防火墙没放行端口UDP被静默丢弃TCP直接报错优先用netstat -lntup检查端口监听状态。第二SELinux阻止了rsyslog的bind日志里会有Permission denied。第三客户端配置的IP或端口不对或者写成了本地回环。逐层检查很快就定位。Filebeat的典型问题是registry文件损坏导致重复发送或漏发。我遇到过一次磁盘满导致registry写入失败重启后Filebeat又从旧位置开始读结果重复灌了好几天的日志到Elasticsearch直接把集群搞到Yellow状态。后来我在系统层面限制Filebeat的内存和文件描述符同时监控/var/lib/filebeat目录的磁盘余量再也没出过这个问题。日志权限也要留意Filebeat以root运行通常没问题但为了安全用普通用户跑时需要确保对日志目录有读权限。最好把常见问题汇总成一张排查表现象可能原因排查命令或手段日志不轮转cron未执行或logrotate配置有误logrotate -d检查cron轮转后新文件为空fd未重开应用不支持信号改用copytruncate或修复postrotatersyslog收不到日志防火墙、SELinux、端口冲突netstat -lntupgetenforce日志时间错乱时区不统一、NTP失效timedatectl status检查NTPFilebeat重复推送registry损坏或误删恢复备份或删旧索引重建ES索引增长过快日志级别过高、保留策略缺失调整日志级别上线索引生命周期策略6. 我的几点实操体会日志管理这件事技术难度真的不高难的是把规则定下来并且长期坚持。我自己的体会是先把轮转和保留策略落到每一台机器上再考虑集中收集集中收集一开始用rsyslog把系统日志归拢起来等真有检索需求了再上Filebeat加Elasticsearch。不要一开始就把架构搞得很重也不要为了“看上去专业”去堆组件。我还有一个比较实用的习惯给所有服务器统一一份logrotate配置基线日志保留周期强制设为14天压缩开启dateext开启每次上线新应用必须同步补充日志轮转配置否则不予发布。这个流程看起来死板但真的能拦住很多生产事故。另外集中收集之后别只当“日志保险柜”每周花一点时间看看日志里的异常趋势往往比监控告警更早发现问题。比如日志里突然出现的连接失败、请求变慢、状态码增多这些在爆发前通常都有微弱信号。最后分享一个小技巧很多日志分析问题其实可以用“先时间窗、再关键字、最后统计”的顺序来拆解把分析步骤固化下来每次排查都按这个顺序走效率会很高。日志管理不是一次性的项目而是一套需要持续维护的习惯。只要把轮转、保留、集中、分析这四个环节理清楚再多的服务器心里都有底。
返回列表