systemd timer 审计与 cron 有何不同?
Linux 计划任务安全核查:异常 crontab 识别、chattr 锁定与回滚清单
做 cron 审计的人多半有一套固定的动作:读配置文件、比对基线、给可疑的行加注释,最后考虑要不要锁定文件。这套动作换到 systemd timer 上,会在三个环节连续失效,而且失效得很安静。
最容易踩的坑是盘点阶段。在只读的步骤里,systemctl list-timers --all --no-pager 能列出定时器以及上一次和下一次触发时间,但这份输出并不能告诉你任务到底执行了什么。反过来,如果只盯着 systemd 的 unit 文件目录,又会漏掉那些文件存在、但已经被停用的定时器。在 cron 里,“存在”和“会跑”基本是一回事;在 systemd 里,这两件事是分开的。
定时器不是一行任务,是一对 unit
cron 的审计对象粒度是一行,命令、时间、执行用户都写在同一行里,读一行就能判断。timer 只负责触发,真正干活的是它拉起的那个 unit。审计时看到 list-timers 的输出,只拿到时间规则,看不到命令指向哪个脚本、以哪个账号身份运行、带了哪些环境变量。要判断这一条能不能信任,必须从 timer 追到它触发的 unit,再读那个 unit 的完整定义,然后回到脚本本身核对属主和修改时间。cron 里一次 grep 能完成的事,在这里往往要沿引用链走三步。
还有一类反过来的情况:unit 文件还在,timer 却没有了;或者 timer 还在,它触发的 unit 已经被替换或者删掉了。这类只存在于一边的残留文件,不会出现在任何一份“任务清单”里,但同样值得记录。
文件内容之外,状态本身也是审计对象
cron 的变更几乎都会落到文件里,所以做基线快照、定期比对 diff 就够了。systemd 多了一层:unit 文件的内容和它的启用状态是两个独立的维度。同一份文件,处于启用和停用两种状态都合法,行为却完全不同。只比对文件哈希,看不出有人在某天把某个定时器停掉,或者把另一份原本安静的文件启用了。
因此 timer 的基线要同时记录两样东西:文件内容和运行状态(是否启用、上次触发时间、下次触发时间)。这两者一旦对不上,就说明有人在文件之外动过配置,这比文件内容本身更值得追查。
触发语义变了,日志入口也变了
cron 的时间是日历上的点,看表达式就能推算出执行时刻。timer 除了日历规则,还支持“开机后经过多久”这类相对时间,以及错过触发点之后要不要补跑的语义。这些行为光读配置文件读不出来,得结合运行时状态和实际执行记录判断。
日志的查看入口也换了。cron 看的是 cron 守护进程的日志;timer 拉起的任务则记在自己 unit 名下,要按 unit 去查,而不是按调度器去查。排查“任务到底跑没跑”时,如果还沿用旧的查法,就会得出“没有执行记录”的错误结论。
处置动作同样要拆开看。在 cron 里注释一行就能保留线索;在 systemd 里,“停用某个定时器”和“给 unit 文件加锁”是两回事。给文件加锁,挡的是文件被修改,挡不住一个已经启用的定时器继续触发;把定时器停用,也不等于文件本身已经安全。两个动作要分开做,也要分开验证。
判断准则可以简化成一句话:cron 审计问的是“文件里写了什么”,timer 审计要问“哪些被启用了、它们各自拉起了什么、最近是不是真的跑过”。三份答案对不上,就是该继续往下看的地方。

参与讨论
以前真把定时器清单当全貌看了
文件没变但状态被启用了,这最阴
追 unit 的时候确实容易断链
我们这边就吃过残留 unit 的亏
查日志得先找 unit