/var/log/boot.log 分析:系统服务启动记录

说实话,很多运维干了三五年,都没认真看过 boot.log。他们觉得系统能起来就行,看这玩意儿干嘛?

但我个人习惯,每次接手一台新服务器,第一件事就是翻 boot.log。为什么?因为这里面藏着系统启动时最原始的状态——服务有没有正常加载、有没有被篡改、有没有被劫持,全在这几行日志里。

boot.log 到底记录了啥?

/var/log/boot.log 是系统启动过程中,systemd 或 init 脚本输出的服务启动状态。说白了,就是系统从按下电源键到登录界面出现之间,所有服务的「体检报告」。

我见过不少新手,系统出问题了就去翻 syslog 或 messages,却忽略了 boot.log 这个第一现场。你想想看,如果某个服务在启动阶段就被劫持了,后面的日志还能信吗?

核心价值:boot.log 是系统启动的「原始证据链」,越早的日志越难被篡改。

如何读取 boot.log?

先看看文件长什么样:

# 查看最近一次启动的 boot.log
cat /var/log/boot.log

# 或者用 journalctl 查看更详细的启动信息
journalctl -b -0 | grep -i "failed\|error\|fail"

典型的输出大概是这样的:

[  OK  ] Started Network Manager.
[  OK  ] Started SSH Server.
[FAILED] Failed to start MySQL Server.
See 'systemctl status mysql.service' for details.
[  OK  ] Started Cron Daemon.

嗯,这里要注意:[ OK ] 不代表绝对安全,[FAILED] 也不一定是坏事。关键看你怎么解读。

识别启动失败的服务

这是最基础的操作。我一般用这条命令快速定位:

grep -i "failed\|fail\|error" /var/log/boot.log

但光找到失败还不够,你得判断:

  • 是配置错误? 比如路径写错了、依赖的服务没起来。
  • 是权限问题? 比如服务以 root 运行,但配置文件被改了属主。
  • 还是被劫持了? 比如服务启动时加载了恶意库文件。

我曾经遇到过一个案例,MySQL 启动失败,查了半天发现是 libcrypto.so 被替换成了恶意版本。这种劫持,在 boot.log 里只会显示「Failed to start MySQL」,但结合 ldd 和 strace 就能揪出来。

我的习惯:每次看到 [FAILED],不要急着重启服务。先跑一遍 systemctl status <service> -l 看完整错误信息,再用 journalctl -u <service> -b 看详细日志。

判断服务被篡改或劫持

这才是今天的重点。服务启动失败,可能是配置问题;但服务启动「成功」了,却不一定安全。

怎么判断?我总结了几个关键点:

检查项 正常情况 可疑情况
启动顺序 依赖关系清晰,按顺序启动 某个服务突然提前或延后启动
启动时间 每次启动耗时基本一致 某次启动耗时突然变长或变短
服务名称 标准服务名,如 sshd.service 出现拼写相似的服务名,如 sshhd.service
加载路径 从标准路径加载 从 /tmp、/dev/shm 等异常路径加载
PID 变化 每次启动 PID 不同但范围稳定 PID 突然跳到异常范围(如 1-100)

举个例子。有一次我检查一台被入侵的服务器,发现 boot.log 里多了一行:

[  OK  ] Started System Resource Monitor.

看着挺正常对吧?但问题是,我从来没装过这个服务。查了一下,发现是攻击者写的一个挖矿程序,伪装成系统服务,随系统启动自动运行。

避坑指南:我曾经因为没仔细看 boot.log,让一个挖矿程序在服务器上跑了整整两周。后来养成习惯,每次系统更新或重启后,都对比一下 boot.log 的服务列表,看有没有「多出来」的服务。

实战:用 boot.log 揪出劫持服务

下面是我常用的排查流程:

  1. 获取基线:系统刚装好时,保存一份干净的 boot.log。
  2. 对比差异:用 diff 对比当前 boot.log 和基线。
  3. 验证服务:对每个新增或变化的服务,用 systemctl cat 查看其 unit 文件。
  4. 检查依赖:用 systemctl list-dependencies 看服务依赖了哪些库。
  5. 交叉验证:用 lsof 和 ss 确认服务监听的端口和连接。

这里有个小技巧:

# 提取本次启动的所有服务名
journalctl -b -0 | grep "Started\|Starting" | awk '{print $NF}' | sort -u > current_services.txt

# 对比基线
diff baseline_services.txt current_services.txt

如果发现多了服务,别急着删。先看看它是什么:

systemctl cat <可疑服务名>
systemctl status <可疑服务名> -l

我曾经用这个方法,发现了一个伪装成 networkd-dispatcher 的后门。它的 unit 文件里写的是启动一个 Python 脚本,而这个脚本会反向连接 C2 服务器。

SVG:boot.log 安全分析流程

boot.log 安全分析流程 读取 boot.log 提取服务启动列表 对比基线服务列表 服务一致 → 继续监控 发现异常服务 深入调查 unit 文件 确认劫持 → 应急响应 提示:建议每次系统更新后都重新生成基线,避免误报

总结几个实用命令

最后,把我常用的几个命令整理一下:

# 1. 查看本次启动所有服务状态
journalctl -b -0 --no-pager | grep -E "Started|Starting|Failed"

# 2. 只看失败的服务
journalctl -b -0 --no-pager | grep -i "failed"

# 3. 查看某个服务的启动日志
journalctl -u sshd.service -b -0 --no-pager

# 4. 对比两次启动的服务列表
journalctl -b -1 | grep "Started" | awk '{print $NF}' | sort > boot_prev.txt
journalctl -b -0 | grep "Started" | awk '{print $NF}' | sort > boot_curr.txt
diff boot_prev.txt boot_curr.txt

# 5. 检查服务启动时间
systemd-analyze blame | head -20

个人经验:我习惯在每台服务器上写一个 cron 任务,每天凌晨把 boot.log 和 journalctl 的快照备份到远程日志服务器。这样即使本地日志被清,也能追溯历史启动记录。

记住,boot.log 是系统安全的「第一道防线」。很多攻击者会清理 auth.log 和 syslog,但往往会忽略 boot.log。你想想看,如果能在攻击者清理证据之前,就从 boot.log 里发现异常,是不是就抢占了先机?