马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
定时任务这块,最常见的坑不是「不会写表达式」,而是「脚本手动执行没问题,交给 crontab 就失败」。本文从一个真实需求切入:每小时进入 /home/threeinf 目录执行 sh run.sh restart,把配置过程、验证方法和那个必踩的环境变量坑一次讲透。
一、场景
要求:每小时定时到 /home/threeinf 目录下,执行 sh run.sh restart。
注意「进入目录」这个动作本身是要写进 crontab 的——cron 的工作目录是用户的家目录(通常是 ~),不会自动切到脚本所在目录。如果脚本里写的是相对路径,不切目录就会找不到文件,这是很多人配完没反应的第一个原因。
2.1 编辑定时任务列表
crontab -e
这个命令相当于编辑当前用户的 crontab 文件,第一次执行会让你选一个编辑器,选 vi 之后就是熟悉的 vi 界面。跟常规 vi 操作一样:按 i 进入编辑,改完按 Esc 再输入 :wq 回车保存退出。
2.2 添加这条任务
0 * * * * cd /home/threeinf && sh run.sh restart
五个星号位置的含义依次是:分、时、日、月、周。这条的意思就是「每小时的第 0 分钟,进入 threeinf 目录再执行重启」。用 && 连接可以保证前面的 cd 成功才执行后面的脚本,比单独写两行更稳妥。
2.3 查看已有任务
crontab -l
能列出刚才加的那条,说明写入成功。
2.4 重启定时服务
systemctl restart crond.service
注意服务名:CentOS / RHEL 系列是 crond,Ubuntu / Debian 系列是 cron。用错服务名会提示 Unit not found。
2.5 看执行日志
tail -f /var/log/cron
有输出结果就说明任务真的被触发了。CentOS 7+ 的 cron 日志 也可能在 /var/log/cron,如果没内容,检查 /etc/rsyslog.d/ 下 cron 相关的日志 规则是否启用。
三、核心坑:脚本手动执行成功,crontab 执行失败
这是最让人困惑的现象:同一个脚本,你登上去手工跑 sh run.sh restart 一切正常,丢给 crontab 就报错或者没反应。
3.1 原因
crontab 执行任务时不会默认从用户的 profile 文件里读取环境变量。我们登录 Linux 时,/etc/profile、~/.bash_profile、~/.bashrc 这些配置文件会被自动执行一遍,里面定义的 PATH、JAVA_HOME、LD_LIBRARY_PATH 等变量也就随之生效。但 cron 启动进程时走的是另一条路径,没有登录 shell 的概念,上述文件不会被执行,所以脚本里用到的命令路径、环境变量全都是空的。
结果就是:脚本里写 java -version 找不到命令,或者 $JAVA_HOME 展开为空导致启动失败——而你手工执行时因为 profile 生效,一切正常。
3.2 解决办法
在 shell 脚本开头(#!/bin/sh 那一行之后)显式 source 一次配置文件:
#!/bin/bash
source /etc/profile
source ~/.bash_profile
这两行加上去,脚本在 cron 环境里就能拿到和用户登录时一样的变量。如果脚本路径里有中文或者有特殊字符,记得在开头加 export LANG=zh_CN.UTF-8,避免编码问题。
另一种做法是在 crontab 里直接写全路径,比如 0 * * * * cd /home/threeinf && /usr/bin/sh /home/threeinf/run.sh restart,把所有依赖的命令都用绝对路径指定。两种方式选一个,别混用——混用会让排查变得非常绕。
四、表达式与写法上的几个细节
- 执行间隔:
*/5 * * * * 是每 5 分钟,0 * * * * 是整点,30 2 * * * 是每天凌晨 2 点半。
- 输出重定向:cron 默认会把任务的输出发到用户邮箱,脚本里有大量输出时会攒一堆邮件。不想要的话在末尾加
> /dev/null 2>&1;反过来,出故障时把输出重定向到文件更好排查:> /tmp/run.log 2>&1。
- 用户区分:
crontab -e 编辑的是当前用户的任务;要给系统级任务写 /etc/crontab,那里多一个用户字段。别把用户任务写错地方。
- 秒级任务:cron 最小粒度是分钟,需要秒级只能用脚本循环或专用调度器。
五、排查清单
crontab -l 确认任务在。
tail -f /var/log/cron 看任务有没有被触发、触发时间对不对。
- 把脚本的 stdout/stderr 重定向到日志文件,看真实报错。
- 检查脚本执行权限:
chmod +x run.sh,或者像本文这样直接写 sh run.sh 绕过执行位。
- 检查执行用户是否有目录读写权限,cron 通常不以 root 身份跑。
把这几步走顺,定时任务基本就不会出意外。关键是记住一句话:cron 里没有登录 shell,所有环境变量都得自己补上。
qidao123.com企服评测-应用市场 编辑提示 |