systemd timer 排查
systemd 提供的定时机制与 cron 平行存在:一个的 .timer 单元负责排期,配对的 .service 单元负责执行动作。两者的差异在于 timer 支持开机后延时、上次执行后间隔、随机延迟与错过的任务补跑等相对时间设定,因此从排期反推触发时间比 cron 更复杂。排查时要注意一个原则:timer 只是触发器,真正要看的是它拉起的那个服务在做什么。
基本信息
| 清单命令 | systemctl list-timers --all 显示全部定时器与下次触发时间 |
|---|---|
| 配对关系 | xxx.timer 触发同名的 xxx.service,也可通过 Unit= 指定其他单元 |
| 查看内容 | systemctl cat 单元名 可同时看到 timer 与 service 内容 |
| 排期关键字 | OnCalendar 绝对表达式、OnBootSec 开机后、OnUnitActiveSec 上次执行后 |
| 随机延迟 | RandomizedDelaySec 会在排期上叠加随机偏移,触发时间不精确 |
| 补跑选项 | Persistent=true 表示错过的任务在下次开机后补跑 |
典型使用场景
- 排查木马被定时拉起:cron 干净但进程仍周期性出现
- 找出异常定时器背后的执行动作与服务单元
- 核对某个定时任务是否为业务或系统自带
- 查看下次触发时间,为处置排定窗口
- 做基线时留存定时器清单供差异比对
排查定时器全貌
排查定时器全貌
systemctl list-timers --all --no-pager | head -n 30 # 排期总览
systemctl cat suspicious.timer suspicious.service 2>/dev/null # 触发器与动作一起看
sudo ls -lt --time-style=full-iso /etc/systemd/system/*.timer 2>/dev/null | head
systemctl list-unit-files --type=service --state=enabled | head -n 30 # 被 timer 拉起的服务也多处于启用状态
sudo systemctl status suspicious.timer --no-pager | head -n 15 # 最近触发情况
journalctl -u suspicious.service --since '-7 days' --no-pager | tail -n 20 # 实际执行记录常见排期设置
| 设置 | 含义 | 排查提示 |
|---|---|---|
| OnCalendar | 按日历表达式定时 | 类似 cron,但表达式语法不同,需逐字段读 |
| OnBootSec | 开机后多长时间触发 | 后门常用几分钟到几小时的延时 |
| OnUnitActiveSec | 上次执行后间隔多久再触发 | 从清单看不到规律,要看 service 的最后执行时间 |
| RandomizedDelaySec | 叠加随机延迟 | 触发时间会在窗口内漂移,不能按分钟对齐 |
| Persistent | 错过的任务开机后补跑 | 关机期间跳过的触发会在开机后立刻执行 |
只查 timer 文件容易得出「没看到什么」的结论:真正执行的动作写在配对的服务单元里。排查时用 systemctl cat 把两个单元一起打印出来,再结合 journalctl 的执行记录确认它是否真的跑过。
用户级定时器同样能实现持久化:普通用户可以管理自己的 systemctl --user 定时器,目录在用户家目录下。以 root 身份执行 systemctl 看不到,需要逐用户检查。