Crontab中使用printf打印时间报invalid directive错误如何解决
问题根源
- Shell不兼容:Ubuntu系统的crontab默认使用
/bin/sh(指向dash)作为执行shell,%()T是bash内置printf的扩展日期格式指令,dash的printf不支持该语法,因此会报invalid directive错误。你在终端执行正常是因为终端默认使用bash作为交互shell。 - 你已经做了%符号的转义,这部分操作是正确的,问题不在这里。
解决方法
有三种常用的可行方案,按需选择即可:
方案1:指定crontab使用bash作为默认shell
在你的crontab配置最顶部添加一行声明:
SHELL=/bin/bash
之后你的原有任务配置只需额外添加错误输出重定向即可正常运行:
0 * * * * { printf "\%(\%Y-\%m-\%d \%H:\%M:\%S)T Updating Certs\n"; sudo certbot renew --post-hook "systemctl reload nginx.service postfix.service dovecot.service"; } >> /home/ubuntu/logs/certbot.log 2>&1
方案2:显式调用bash执行任务
不想修改crontab全局shell的话,可以直接把命令包裹在bash调用中:
0 * * * * /bin/bash -c '{ printf "\%(\%Y-\%m-\%d \%H:\%M:\%S)T Updating Certs\n"; sudo certbot renew --post-hook "systemctl reload nginx.service postfix.service dovecot.service"; }' >> /home/ubuntu/logs/certbot.log 2>&1
方案3:用date命令替代printf的日期格式化(兼容性最优)
如果不想依赖bash特性,直接用date命令输出时间,兼容所有shell,不需要修改默认shell配置:
0 * * * * { echo "$(date +"\%Y-\%m-\%d \%H:\%M:\%S") Updating Certs"; sudo certbot renew --post-hook "systemctl reload nginx.service postfix.service dovecot.service"; } >> /home/ubuntu/logs/certbot.log 2>&1
额外优化建议
如果这个任务是写在普通用户的crontab里,需要确保当前用户执行certbot和systemctl reload的sudo操作不需要输入密码,否则任务会执行失败。更推荐把这条定时任务写到root用户的crontab中(执行sudo crontab -e编辑),去掉命令中的sudo前缀即可,权限更合理也不需要额外配置sudo规则。
内容的提问来源于stack exchange,提问作者Ajay Varghese
相关产品推荐
相关产品推荐

