1. 为什么要专门花一天整理Linux日志管理前阵子排查一个线上小问题折腾了我一整个下午。某服务到点没执行进程在跑、配置看着也正常我翻遍了自己能想到的所有配置文件最后还是靠同事提醒了一句你看了系统日志没有才在message日志里找到一条被SELinux拦截的记录。那件事让我挺受触动的——平时写命令、改配置都很熟练但真到了出问题的时候却对系统最基础的黑匣子毫无头绪。所以这个学习日我不打算学什么花哨的新工具就老老实实把Linux日志管理这一整套体系梳理一遍。日志管理这件事说小了是出问题的时候知道去哪翻日志说大了其实是三件事故障排查、安全审计、性能分析。故障排查不用说进程挂了、任务没跑、网络连不上日志是最直接的线索来源。安全审计则依赖登录记录、命令记录、服务访问记录比如谁在什么时间从哪个IP登入过系统这些都要靠日志还原。性能分析稍微进阶一点可以通过日志判断系统负载规律、服务响应趋势虽然不是专业监控工具那种精度但作为日常观察手段完全够用。我今天给自己定的学习目标是把Linux日志从产生、写入、存储、轮转到分析这条链路完整走一遍搞清楚每一个环节在做什么、有哪些关键的配置文件、常见的坑在哪里。学习路线按下面几步走先看日志文件家底和各自用途然后重点学journald和journalctl这套新体系接着是rsyslog的规则配置再做logrotate轮转策略最后用一个真实排错案例把前面学的串起来。如果只看结论Linux日志体系现在其实是两条腿走路一条是传统syslog/rsyslog体系日志以纯文本形式写在/var/log下面好处是人类可读、方便grep坏处是格式不统一、量大了以后查询效率低另一条是systemd-journald体系用二进制格式集中存储自带索引和结构化字段通过journalctl查询效率高信息也更全。两条腿各自承担不同任务现代Linux发行版里通常是并存的journald负责采集rsyslog负责把日志转发到文本文件或远程服务器。把它们之间的关系理清楚后面的操作就不容易乱了。2. /var/log目录下的家底常用日志文件与用途学日志管理第一步不是急着配什么而是先把自己系统里已有的日志文件认全。大多数发行版的日志都集中在/var/log下但不同系统、不同安装软件会各有差异。我拿一台常用的机器执行了ls -lh /var/log/把主要文件的用途整理了一下日志文件主要记录内容常见用途/var/log/messages系统级通用日志包含内核、服务、应用的大部分消息排查系统问题的第一站/var/log/secure安全相关日志主要是认证、登录、sudo操作的记录查看登录失败、暴力破解/var/log/croncron计划任务执行日志排查定时任务不执行/var/log/dmesg内核环形缓冲区消息主要是硬件、驱动信息查看硬件识别、驱动报错/var/log/boot.log系统启动过程的服务输出排查开机阶段的服务异常/var/log/maillog邮件服务日志邮件发送失败排查/var/log/httpd/Apache或Nginx等Web服务日志目录Web访问日志与错误日志/var/log/lastlog每个用户最后一次登录时间二进制查看用户登录历史/var/log/wtmp成功登录的记录二进制确认谁在什么时候登录过/var/log/btmp失败的登录尝试记录二进制排查暴力破解攻击这里面最容易搞混的是三个用户登录相关的二进制文件lastlog、wtmp、btmp。它们不能用cat或者tail直接看得用对应的命令去读取。lastlog命令读取lastlog文件展示每个用户最近一次登录last命令读取wtmp展示历史登录会话记录包括重启记录lastb命令读取btmp展示所有失败的登录尝试。平时做安全巡检时我习惯定期看一眼lastb | head -50如果发现某个IP反复尝试登录基本可以确定有人在扫你。还有几个文件值得单独说。dmesg日志其实有三条读取路径传统方式是dmesg命令直接看内核环形缓冲区但缓冲区容量有限早期的消息会被覆盖所以很多系统同时把启动早期消息写入/var/log/dmesg文件。如果你怀疑是硬件驱动问题、硬盘识别异常、网卡固件报错第一反应应该是看这里而不是去messages里大海捞针。boot.log对排查开机启动慢、某个服务在启动阶段反复失败这类问题非常有用因为它记录的是systemd在开机时逐个启动服务的过程输出能看到服务启动顺序和具体失败点。判断该看哪个日志其实有个简单的经验法则先看messages总览全局再看secure确定是否和认证相关然后根据服务类型去细分类目。比如Web站点访问异常优先看Web服务的错误日志和访问日志定时任务没跑看cron日志登录有问题看secure。虽然journald已经把很多日志统一采集了但我个人还是建议先把传统文件这套体系搞明白因为很多老系统、老脚本还是依赖这些文本文件而且文本文件配合tail和grep做快速排查时依然非常顺手。3. journald与journalctl新时代的日志主战场说完了传统文件接下来是我的学习重点systemd-journald。从CentOS 7、Ubuntu 16.04之后的大版本开始主流发行版基本都切到了systemd体系journald随之成为系统日志采集的第一环。它的核心特点是日志以二进制格式写入按索引存储查询时不需要遍历文本文件速度非常快同时每条日志都带结构化字段——时间、主机名、进程PID、可执行文件路径、优先级、systemd unit名称等条件过滤起来非常精确。我先说journald和rsyslog之间的关系。journald是采集端和存储端它从内核、systemd服务、各应用程序收集日志默认存在内存或磁盘的journal目录里。rsyslog是转发和落盘端它可以从journald读日志然后按规则把日志写入/var/log下的文本文件或者转发到远程日志服务器。换句话说journald负责收进来rsyslog负责送出去。有的服务只写journal不写文本文件有的服务两边都有查日志时两边交叉验证往往能还原出更完整的事实。journalctl是操作journald的命令行工具我先跑一遍最基本的用法。查看全部日志最简单journalctl这条会输出所有已采集的日志量非常大基本没人会直接用它。日常最常用的是条件过滤我整理了一张速查表过滤需求命令说明只看本次开机journalctl -b区分上次启动和本次启动的问题看上一次启动journalctl -b -1上次启动的日志按时间过滤journalctl --since 2026-01-20 09:00:00精确到秒也可用today、yesterday实时跟踪journalctl -f类似tail -f按服务过滤journalctl -u nginx.service只看某个systemd服务的日志按优先级过滤journalctl -p err只显示err及以上级别也支持数字按进程过滤journalctl _PID1234直接指定PID查看内核日志journalctl -k等价于dmesg的journal版我实际操作时最常用的组合是journalctl -u 服务名 --since today -p warning一次就能把某服务今天以来的警告和错误全部筛出来不再需要一行行翻。这里有个细节-p后面可以跟emerg、alert、crit、err、warning、notice、info、debug这些级别名也可以跟数字0到7。刚用的时候容易把大小写写错——warning不是大写W小写即可。排查服务问题时journald一个很大的优势是能看到服务的标准输出和标准错误输出。以前跑一个脚本或服务输出到控制台的日志经常丢现在只要这个服务由systemd管理它的stdout和stderr也会被journald捕获。也就是说你写print或者echo打出来的内容用journalctl -u 服务名就能看到。这一点对排查服务明明起来了但什么都没写入日志文件的情况特别有用。journald默认在部分系统上只把日志放在内存里/run/log/journal重启就丢。所以要做长期排查、审计留存必须把它改成持久化存储。修改方式很简单编辑/etc/systemd/journald.conf[Journal] Storagepersistent改完后重启服务生效systemctl restart systemd-journaldStorage的值有三种persistent表示写入磁盘目录默认在/var/log/journalvolatile表示只存内存即/run/log/journalauto表示自动决定——如果有/var/log/journal目录就用持久化否则用内存。改成persistent后systemd会自动创建/var/log/journal目录。这里有个实际坑如果目录权限不对journald会回退到内存模式所以改完配置后最好用journalctl --verify检查一下当前journal文件是否正常同时用ls -ld /var/log/journal确认目录存在。还一个值得关注的是journald的磁盘占用上限。采集的日志多了以后/var/log/journal会持续增长如果不加限制有把小硬盘撑满的风险。journald.conf里相关的参数是SystemMaxUse表示journal占用磁盘空间的最大值默认是磁盘容量的10%也可以显式指定比如限制为500MSystemMaxUse500M改完同样需要重启journald才生效。在实际生产环境我习惯把SystemMaxUse设置成一个偏小的值再配合后面的logrotate把日志往文本文件转发这样既保证近期的日志好查journald索引快又保证长期日志有归档文本文件可以压缩轮转。4. rsyslog规则配置把日志送到该去的地方journald把日志收进来了但很多场景下我们还是需要把日志按规则写到特定文件里比如单独给某个应用建一个日志文件或者把远程设备的日志全部收到一台服务器上集中管理。这个活儿传统上归rsyslog管。rsyslog的配置结构我捋了一下主要分成三块第一是模块加载比如加载imuxsock模块采集本地socket日志、imjournal模块从journald读日志第二是全局配置比如日志文件权限、模板定义第三是规则配置也就是最核心的什么样的日志写到哪儿。配置文件的主入口是/etc/rsyslog.conf通常它还会include /etc/rsyslog.d/目录下的所有.conf文件所以自定义规则最好放在rsyslog.d下面新建独立文件不要直接改主文件。规则的基本格式只有两列选择器(selector) 动作(action)选择器由设备(facility).级别(priority)组成。设备表示日志来源类别常见的有auth认证、authpriv私有认证、cron计划任务、daemon守护进程、kern内核、mail邮件、user用户进程等级别则和journald一样从emerg到debug。动作可以是一个文件路径也可以是一组目标。举个例子把cron相关的所有日志单独写到/var/log/cron_custom.logcron.* /var/log/cron_custom.log把authpriv的所有级别写入/var/log/secureauthpriv.* /var/log/secure级别还有一个语法需要注意cron.info表示只记录info及以上级别cron.info表示只记录info这一级cron.!info表示记录info级别以下的。在写规则之前最好先通过logger -p cron.info test message这样的命令打一条测试消息再用tail验证规则是否生效。logger命令是手动往syslog发消息的最简单工具做规则调试时必备。严格来说机器上已经存在的传统日志文件大多不是天生就有的而是由rsyslog规则生成的。比如/var/log/messages对应规则通常是*.info;mail.none;authpriv.none;cron.none /var/log/messages这条规则的含义是记录所有设备info级别以上的日志但排除mail、authpriv、cron这三个设备。理解了这个语法你再看任何rsyslog配置都不会发怵——无非就是选设备、选级别、排除设备、落到文件这四件事。远程日志集中管理是rsyslog另一个常见用途。假设你在内网有一台日志服务器想让所有客户端把日志发过来服务器端需要开启监听端口客户端配置对应转发。服务器端在rsyslog.conf中启用module(loadimtcp) input(typeimtcp port514)客户端则在规则里把日志转发到服务器IP*.* 192.168.1.100:514表示使用UDP协议两个即表示TCP协议。实际部署时我吃过一个亏远程转发默认用的是UDPUDP丢包不重传日志一转出去就不可控了。所以内网环境如果是关键业务日志建议直接走TCP并且客户端本地保留一份副本不要只依赖远程转发。另外服务器端要注意防火墙放行对应端口SELinux对rsyslog监听非标准端口也可能有拦截遇到转发不通时先用setenforce 0做一次临时验证确认是SELinux问题再调策略或者用audit2allow生成放行规则。关于rsyslog的性能还有一个不常被提到但很重要的概念日志写入时机。rsyslog对每个写文件动作有一个缓存机制默认情况下日志不是每条立即落盘的积累到一定量或者到达刷盘周期才写入。这样做效率高但带来的风险是系统突然断电时最后一部分日志可能丢失。管理员可以在规则文件路径前加一个-号表示异步写入不加负号表示同步写入。比如-/var/log/app.log就是异步。同步写入更安全但更慢适合关键日志异步写入性能好但可能丢尾部日志适合高频低价值日志。这个选择没有绝对对错但一定要知道它的存在。5. logrotate轮转策略防止日志把磁盘撑爆日志最让人头疼的问题就是只涨不消。哪怕是一个访问量一般的Web服务日志日积月累也能吃掉几个GB更不用说那些疯狂打日志的应用。所以日志轮转log rotation是日志管理里绝对不能跳过的一环。Linux下默认用的是logrotate它通过cron定时任务每天执行一次按配置对日志文件进行切割、压缩、清理。logrotate的核心配置在/etc/logrotate.conf通常还会有/etc/logrotate.d/目录存放各服务的独立配置。主配置里有一行很关键include /etc/logrotate.d这表示所有/etc/logrotate.d下的文件都会被加载。我建议每个应用单独建一个配置文件不要把所有规则堆在主配置里这样每个应用都可以自己定义轮转频率、保留份数、压缩策略。logrotate配置文件的基本语法我拿一个模拟应用日志来举例文件/etc/logrotate.d/myapp/var/log/myapp/*.log { daily rotate 7 compress delaycompress missingok notifempty copytruncate }我们一行一行看这些指令是什么意思。daily表示每天轮转一次此外还有weekly和monthly。rotate 7表示保留7个旧日志文件超过7个就删除最旧的。compress表示旧日志用gzip压缩磁盘占用能省不少如果日志本身就是高重复文本压缩率通常很高。delaycompress的意思是本次轮转出来的那个文件先不压缩下次轮转时再压缩这样做是为了给正在写日志的程序留一个缓冲也方便你查看最近一天的旧日志。missingok表示日志文件不存在时不要报错。notifempty表示日志为空就不轮转。copytruncate是很多应用日志的保命选项——它先复制当前日志文件为轮转文件然后清空原文件这样的好处是应用进程不需要重启就能继续写日志。和copytruncate对应的是create默认很多系统服务用的是create方式先把原日志文件改名成轮转文件然后新建一个同名空文件应用进程需要能感知文件被替换通常是重新打开文件描述符才能继续正常写入。如果应用不支持重新打开文件描述符用create方式就会出现日志还在往旧文件里写的情况——旧文件已经被轮转改名了新日志就写到旧文件里去了看起来就像日志卡住不更新。这时候要么改用copytruncate要么在轮转后执行postrotate脚本重启应用二选一。配置完成之后一定要先做测试不要干等每天的执行。logrotate提供两个参数-d表示debug模式只打印执行计划但不实际执行-f表示强制执行轮转可在修改配置后立即验证效果。比如logrotate -d /etc/logrotate.d/myapp logrotate -f /etc/logrotate.d/myapp先dry-run看日志会怎么切、切几份、压缩不压缩确认符合预期后再强制执行。我实际用过很多次-f不只是验证配置也有实用场景比如某服务日志在两天内涨了3GB你等不到下一次轮转直接手动强制轮转一次就能把空间收回来。很多人在配置logrotate时遇到的困惑是我配了size但没生效。size指令长这样size 100M它表示当日志文件超过100M时轮转和daily/weekly并不冲突谁先满足条件就谁触发。需要注意没生效往往是执行时间还没到或者cron任务跑了但日志文件没超过阈值。另外还有个顺序问题如果同时写了daily和size默认是每天检查一次超过size就转没超过就不转。所以别指望size能精确到MB级别的实时控制它有个时间窗口。想验证就用-f强制跑一次直接看结果。日志轮转之后还有一件容易被忽略的事权限保持。很多应用日志写入时有特殊权限要求轮转生成的新文件如果权限不对应用就写不进去了。logrotate提供了create指令可以指定新文件的属主和权限比如create 0640 appuser appgroup如果没有明确配置默认继承原文件权限但在copytruncate方式下原文件没有被替换所以权限天然保持不变。这也是我偏好copytruncate的原因之一。同时要注意如果日志目录本身属主不是应用用户应用可能因为目录权限无法创建新文件排查时看一下日志文件的属主和目录权限往往比盯着配置文件本身更高效。6. 一次真实排错从日志里挖出问题根源学完前面的知识光看不练还是不行。我把前阵子那次把我卡了一下午的真实排错过程完整复盘一遍用今天学的日志手段重新走查算是给自己做一次实践检验。当时的情况是这样的某台机器上有个数据同步服务模拟项目X按设计应该每天凌晨2点从外部拉取数据。某天早上检查时发现昨天的数据没有同步成功。服务进程显示在运行systemctl status没有红色报错配置文件里的定时表达式看起来也是对的——这种情况最容易让人误判因为表面一切都正常。我重新走了一遍排查链路。第一站用的就是journalctl按时间窗口锁定问题区间journalctl -u sync-service --since yesterday --until today -p warning输出立刻就出现了有价值的线索凌晨2点01分左右有一条关于连接上游服务超时的报错后面跟着几条重试失败记录。看到这个问题的大方向就清楚了——不是定时没触发而是触发之后连接远端失败。但为什么服务还是运行中呢因为这类同步服务通常有守护模块任务线程失败了主进程不会退出只是同步状态被标记为失败所以systemd层面看起来没有任何异样。这个案例其实说明一个很实在的道理服务进程活着不等于任务成功必须以任务结果日志为准不能只看进程状态。为了交叉验证我又去翻了/var/log/messages在同一时间段有没有网络相关异常grep 2:0[0-9] /var/log/messages | grep -i error确实发现了网络模块的几处连接被拒的提示和时间窗口对得上。到这里结论基本可以收束了同步任务在凌晨2点尝试连接外部数据源失败。后续再配合上游服务方的排查确认是对方临时维护导致端口短暂不可用。整个过程如果用一句话总结就是先看业务日志定问题性质再看系统日志找旁证两个来源互相印证排查结果才扎实。复盘这次排错我给自己总结了三条心得。第一排查前先把时间窗口定准用--since/--until把日志范围缩小到问题发生的前后各半小时能省掉大量无效浏览。第二别只看一个日志源journalctl和文本日志各有所长journald里往往有systemd特有信息比如服务的退出码、报错路径而传统messages里可能有网络模块、内核模块的更细记录两边对不上时再扩展搜索范围。第三日常就要养成给关键应用打结构化日志的习惯——时间戳、错误级别、上下文信息缺一不可。如果这个同步服务当时在日志里打印了同步失败上游返回503我连messages都不用翻就能定位。顺便说一个排错时的小技巧journalctl默认输出的时间格式是系统时区的如果你用--since过滤时用了错误时区会什么都查不到。改起来也不难可以在/etc/systemd/journald.conf里调整时间相关配置但更简单的是在命令行直接加环境变量比如TZAsia/Shanghai journalctl --since 2026-01-20 02:00这样查询时间就和本地时区对齐了。平时遇到的为什么journalctl查不到日志问题至少有一半是时区或时间范围写错了。7. 学习日志的留档与后续计划这次日志管理的系统学习到这儿基本收尾。按惯例我把今天弄明白的核心知识点做了个清单方便后续翻查同时给下一步学习留个目录Linux日志体系是journald收集、rsyslog转发落盘、logrotate轮转清理的三段式结构。文本日志先看messages认证问题看secure定时任务看cron二进制登录日志用last/lastb读取。journalctl按服务、时间、优先级组合过滤是排查问题的最高效入口持久化必须显式配置Storagepersistent。rsyslog规则掌握selector和action两列即可远程转发优先TCP并要求本地留副本。logrotate配置完先用-d验证再用-f生效copytruncate适合不支持重开文件描述符的应用。下一步我打算继续深入两个方向。一是把journald的字段索引机制再往深挖一层看看在日志量达到日均几GB的服务上怎么设计合理的journal大小和查询策略二是系统学习一下集中化日志栈的搭建用消息队列加全文检索引擎把多台机器的日志汇总到一处这样以后排查跨机器问题时就不用一台一台登录翻日志了。这两个方向都和实践强相关等有阶段性结果了我再单独写一篇。最后留一句个人体会日志管理看起来是基础得不能再基础的运维技能但恰恰是关键时刻最能救命的东西。与其等出了大事再临时学不如现在就花一天把体系搭好、把命令练熟。今天把该配的持久化、该写的轮转规则都在自己的实验机器上落实了一轮那种心里有底的感觉比记住多少条命令都值。