如何清理crontab中的异常控制字符并解决「error: bad minute」错误
兄弟,我太懂你这种明明没折腾啥,crontab突然报错的烦躁了!先给你拆解问题——你看到的每行末尾$,和你真正的「bad minute」错误,其实是两个问题,咱们一个个解决:
先搞清楚:那些$字符是啥?
你在vi里看到的每行末尾$,大概率不是真的“异常控制字符”,而是vi的换行符可视化标记!如果之前不小心开了list模式(用来显示空白字符),vi就会把每行的换行符显示成$。
要关掉这个显示,在vi编辑crontab的时候,输入::set nolist
按回车,$就消失了——是不是瞬间清爽?
如果真的存在隐藏的控制字符(比如Windows格式的换行符^M,这种才会真的搞坏crontab),那可以用vi转换格式::set fileformat=unix
然后保存退出即可。或者用Mac的sed命令批量清理(先导出crontab到临时文件,处理后再导入):
crontab -l > /tmp/my_crontab sed -i '' 's/\r$//' /tmp/my_crontab crontab /tmp/my_crontab
真正的问题:「bad minute」报错的根源
你后来贴的crontab内容暴露了核心问题——你把[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"这种shell命令直接写在了crontab里!
crontab的语法规则很严格:每行要么是环境变量设置(比如VAR=值),要么是定时任务行(开头是5个时间字段)。那些初始化nvm的shell语句,既不是变量设置,也不是合法的时间行,crontab会把它们当成任务时间来解析,自然就报「bad minute」了。
解决办法:把初始化逻辑移到脚本里
最稳妥的方式是把所有环境变量、nvm初始化代码都塞进你的cron-truebug.sh脚本中,让crontab只负责触发脚本:
- 先给脚本加上执行权限:
chmod +x /Users/punkish/Projects/zenodeo3/bin/cron-truebug.sh
- 修改
cron-truebug.sh的开头,把初始化内容加进去:
#!/bin/bash # 脚本开头加入环境变量和nvm初始化 HOME=/Users/punkish export NODE_ENV=cron export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh" [ -s "$NVM_DIR/bash_completion" ] && source "$NVM_DIR/bash_completion" # 下面放你原来脚本的内容 # ...
- 最后简化你的crontab内容,只保留任务行:
0 0 * * * /Users/punkish/Projects/zenodeo3/bin/cron-truebug.sh
备选方案:在crontab里用bash包裹命令
如果不想改脚本,也可以在crontab的任务行里直接用bash执行完整逻辑:
HOME=/Users/punkish APPDIR=Projects/zenodeo3 NODE_ENV=cron NVM_DIR="$HOME/.nvm" 0 0 * * * /bin/bash -c 'source "$NVM_DIR/nvm.sh"; cd $HOME/$APPDIR && bin/cron-truebug.sh'
这样crontab只会把最后一行当成任务行,前面的都是合法的环境变量设置,就不会再报错啦!
备注:内容来源于stack exchange,提问作者punkish

