/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 揪出劫持服务
下面是我常用的排查流程:
- 获取基线:系统刚装好时,保存一份干净的 boot.log。
- 对比差异:用
diff对比当前 boot.log 和基线。 - 验证服务:对每个新增或变化的服务,用
systemctl cat查看其 unit 文件。 - 检查依赖:用
systemctl list-dependencies看服务依赖了哪些库。 - 交叉验证:用
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 安全分析流程
总结几个实用命令
最后,把我常用的几个命令整理一下:
# 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 里发现异常,是不是就抢占了先机?