at命令不支持now + 30 minutes等自然语言时间,需用date命令生成标准格式时间字符串再传给at,如echo "/opt/bin/do-failover.sh" | at "$(date -d '30 minutes' '+%H:%M')";跨日时须加日期;也可用sleep替代。

在 at 命令中,不能直接用 now + 30 minutes 这种自然语言式表达——at 不解析这种口语化时间描述,它只认标准时间格式(如 HH:MM、midnight、teatime)或带日期的完整时间串(如 2024-06-15 14:30)。
用 date 命令动态生成时间字符串
真正“快速提交延迟割接任务”的做法,是把口语化时间交给 date 解析,再喂给 at:
echo "your-command-here" | at "$(date -d 'now + 30 minutes' '+%H:%M')"- 比如割接脚本是
/opt/bin/do-failover.sh,就写:echo "/opt/bin/do-failover.sh" | at "$(date -d '30 minutes' '+%H:%M')"(now +可省略) - 注意:如果跨日(比如现在 23:45,加 30 分钟),
date -d会自动算出00:15,但at默认按今天处理,这时得显式带上日期:echo "... " | at "$(date -d '30 minutes' '+%Y-%m-%d %H:%M')"
别依赖 at 的模糊关键词
at 虽支持 teatime、midnight 这类词,但它不支持 in 30 minutes 或 30 mins later。你输 at in 30 minutes,它会报错或误解成字面意思(比如当成“in”是用户名、“30”是分钟)。
确保 atd 服务开着,且用户有权限
很多服务器默认没开 atd 守护进程,或者把用户禁在 /etc/at.deny 里:
- 检查:
systemctl is-active atd,没运行就sudo systemctl enable --now atd - 确认你不在
/etc/at.deny中;如果文件存在且为空,或只有root,通常没问题;若存在/etc/at.allow,则必须在里面列出你的用户名
替代方案:用 sleep + 后台执行更轻量
如果只是本机临时延时执行(不涉及系统级调度、也不需 at 日志/权限控制),用 sleep 更直接:
-
(sleep 1800 && /opt/bin/do-failover.sh) &(1800 秒 = 30 分钟) - 加
nohup防终端断开:nohup sh -c 'sleep 1800 && /opt/bin/do-failover.sh' > /dev/null 2>&1 & - 适合快速测试或运维救火,不用碰 at 配置和权限

















