应创建 /etc/systemd/system/sec-check.service(Type=oneshot、绝对路径ExecStart、journal日志、TimeoutSec)和同名timer文件,其中OnCalendar设为--* 02:30:00、Persistent=true,并执行systemctl daemon-reload && systemctl enable --now sec-check.timer完成启用。

用 systemd-timer 配置每日凌晨自动执行安全基线巡检,比 cron 更可靠——尤其当系统启动延迟、时钟跳变或任务依赖其他服务时,systemd 能自动重试、记录完整执行上下文,且不依赖 shell 环境变量。
怎么写一个 clean-logs.service 对应的巡检 service 单元
巡检脚本本身不能直接被 timer 调用,必须封装成 service 单元。关键点是:Type=oneshot + RemainAfterExit=yes(可选,仅当需状态追踪)+ 显式指定解释器路径。
-
ExecStart必须用绝对路径调用脚本,例如/usr/local/bin/sec-check.sh;不能写成./sec-check.sh或依赖$PATH - 如果脚本需要 root 权限(比如读取
/etc/shadow、检查内核参数),service文件里不用额外加sudo,只要以 root 用户启用 timer 即可 - 建议加上
StandardOutput=journal和StandardError=journal,确保所有输出进journalctl,方便后续排查 - 若巡检脚本可能运行超时(如扫描大量文件),加
TimeoutSec=600避免被 systemd 强杀
示例 /etc/systemd/system/sec-check.service:
[Unit] Description=Run security baseline check After=network.target <p>[Service] Type=oneshot ExecStart=/usr/local/bin/sec-check.sh StandardOutput=journal StandardError=journal TimeoutSec=600</p>
怎么用 OnCalendar 设置“每天凌晨 2:30”执行
OnCalendar 支持自然语义,但生产环境建议用明确格式,避免解析歧义。注意:它默认按系统本地时区解析,不是 UTC。
- 写成
OnCalendar=*-*-* 02:30:00最稳妥,等价于“每天任意年-任意月-任意日 的 02:30:00” - 别用
daily别名——它实际等价于00:00:00,不是你想要的凌晨 2:30 - 如果服务器有时区切换风险(如跨地域部署),显式加
Timezone=Asia/Shanghai更安全 - 想跳过某天(比如维护窗口)?
systemd不支持条件跳过,得在脚本内部判断日期并 exit 0
对应 timer 文件中 [Timer] 段应为:
[Timer] OnCalendar=*-*-* 02:30:00 Persistent=true
Persistent=true 很重要:如果机器在 02:30 关机/休眠,下次开机后会立即补跑一次,防止漏检。
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
为什么 systemctl list-timers 看不到你的 timer
常见原因不是语法错,而是没完成三步闭环:
- 文件必须放在
/etc/systemd/system/下(用户级 timer 放~/.config/systemd/user/,但巡检通常要 root 权限) - 文件名必须严格匹配:service 名是
sec-check.service,timer 就得叫sec-check.timer,否则Unit=字段对不上 - 每次改完文件,必须执行
systemctl daemon-reload,否则systemctl enable会静默失败 - 启用命令要用
systemctl enable --now sec-check.timer,只enable不start,timer 不会激活
验证是否生效:systemctl list-timers --all | grep sec-check,看到下一次触发时间即成功。
怎么确认巡检脚本真的执行了且没静默失败
靠脚本里 echo 或日志文件不可靠——systemd 可能因权限、路径、环境变量问题根本没跑起来,但 timer 状态仍显示 “waiting”。必须查真实执行痕迹:
- 查 timer 自身状态:
systemctl status sec-check.timer,看TriggeredBy和最近触发时间 - 查关联 service 执行结果:
systemctl status sec-check.service,重点看Active:行和Main PID - 查完整日志:
journalctl -u sec-check.service -S "2026-04-20 02:30:00",带时间范围过滤更准 - 如果脚本里用了
date >> /var/log/sec-check.log,记得确认/var/log目录存在且 service 有写权限——systemd默认不继承用户的 umask
最容易被忽略的一点:巡检脚本开头必须有 #!/bin/bash(或对应解释器),且文件本身要有 +x 权限。否则 systemd 报 Exec format error,但 status 里可能只显示 “failed”,不提示具体原因。










