crontab
程序部署在Linux系统之中,很可能会用到crontab,但是呢,写好的定时任务,可能因为种种错误方式,并没有按着预定的方式运行,如何写出正确的、健壮的定时任务。做一下总结。
入门
原则
- 1、执行的时候,先cd到目录,最稳妥,防止引入了相对变量的文件路径。
- 2、加上环境变量,尤其是
PATH,有时,居然连/usr/local/bin都不在环境变量中。故,最好自己设置一下。 - 3、测试,测试的时候,跳到
cd /路径,再执行,看看能否正常执行。 - 4、测试的时候,直接清空 PATH,只加有关的PATH。(待验证)
编写格式
我们假定,脚本执行的时候,没有任何环境变量,没有直接cd 到项目目录中。
# 先进入目录,再执行,都加上绝对路径
40 17 * * * cd /yd/td/shell && /usr/local/php73/bin/php summary.php
# 下载
*/5 * * * * /bin/curl -s http://repo.yundasys.com/shell/nvme/nvme_status.sh|bash
# 日志输出到文件 错误重定向到 标准输出中 注意是追加模式
01 00 * * * /yd/td2/shell/import_job.sh >> /yd/td2/runtime/cron/log.txt 2>&1
# 或者直接丢弃
* * * * * /usr/local/gse/agent/bin/gsectl watch >/dev/null 2>&1
# 但是,如果要分隔文件呢? 下面直接执行就可以,但是,却
/yd/td2/shell/main.sh >> /yd/td2/runtime/cron/log`/usr/bin/date +%Y%m%d%H%M%S`.txt 2>&1
# 如果错误、标准输出,写到不同的文件中,
25 */2 * * * /bin/bash /etc/titanagent/agent_update.sh >> /var/log/titanagent/check.o.log 2>> /var/log/titanagent/check.e.log
脚本示例
#!/bin/bash
# 2021年8月10日 脚本导入任务
# 01 00 * * * /path/to/myshell.sh >> /path/to/log.txt 2>&1
BASEDIR=$(cd `dirname $0`;pwd)
cd $BASEDIR
source /root/.bash_profile
export PATH=/usr/local/bin/:/usr/local/greenplum-db/bin/:$PATH
logmsg(){
echo "`date '+%Y-%m-%d %H:%M:%S'` $1"
}
定时脚本启动的不同
定时脚本,在执行的时候,并不会加载一些环境变量的脚本。查阅下面文章。
https://blog.csdn.net/gaojing2240/article/details/103908656
定时格式
分 时 日 月 周
# 每分钟执行一次
* * * * *
# 每半小时执行一次
*/30 * * * *
# 周末中午12点执行
0 12 * * 6,7
# 工作日,凌晨两点执行
0 2 * * 1-5
# 两点到4点,12点到16点的整点执行一次
0 2-4,12-16 * * *
符号说明
/ ,表示每,设置步长。
-,表示范围,能与,联合使用。
,,多个值或范围用逗号分隔。
以分钟为示例,复杂的组合如下:
*/3,4,5,8,50-59
FeHelper的定时工具,用来调试还不错。
crontab -e
使用crontab -e的方式,来编辑定时任务。不同的用户,对应的不同的定时任务。运行任务时,以该用户的角色、权限来运行脚本。
关于权限与安全,比如,以root方式运行/mytest.sh,假入该脚本权限为0777,那么普通用户通过修改该脚本,添加特殊指令,并等待定期以root触发,然后很可能权限会泄漏。
关于环境变量,很有脚本运行的时候,会缺少相关的环境变量。另外,最好先cd到执行的目录中。
示例:
# 先cd到脚本文件目录,然后使用php的全路径来运行脚本,虽然环境变量中有php的路径
# 但是,crontab运行时,缺找不到。
0 9 * * 1 cd /yd/td2/shell && /usr/local/bin/php diskstatus.php
要不要先cd到目录中,再执行,这个要看,php文件,如果它中使用相对文件路径引用其他文件,所以,最好先cd到目录中。
环境变量,可能shell中运行缺时找不到。
之前遇到的一个问题是:hexo博客,也是环境变量上中不到相关的程序。
# 用alias解决
alias php='/usr/local/bin/php'
# 使用变量的方式
phpbin='/usr/local/bin/php'
$phpbin test.php
# 环境变量PATH 自己增加
PATH
crontab -l
查看已有哪些定时任务。
配置
在我的ubuntu上看到定时任务上面有如下配置,可以作为脚本运行时的配置参考。如下:
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/tmp
其他
定时任务存放的地方(centos):
/var/spool/cron/root
貌似,也可以直接通过修改该文件,来增加定时任务。
日志
所有用户的日志都在这个里面,如果脚本无法执行,可以查看该文件,确定无法执行的原因。但是,需要root权限。
/var/log/cron
ls /var/log/cron*
邮件
当crond执行任务失败时会给用户发一封邮件。(如何开启?),可能有详细的失败日志。
vi /var/spool/mail/root
日志文件重定向
0 6 * * * $HOME/for_crontab/myshell.sh >> $HOME/for_crontab/mylog.log 2>&1
原因排查
首先,先将原来定时任务执行频率调整更低,如* * * * *,然后调试。
执行执行定时任务的脚本,看是否能执行。(能执行,而定时任务下不能执行,可能是某些环境变量缺失。如,简写的php命令不识别。)
查看错误日志。找到原因描述。
错误示例
定时任务:
*/30 * * * * /path/to/hexo_blog.sh > /path/to/hexo.log 2>&1
错误的代码
alias node="/usr/local/node/bin/node"
alias hexo="/usr/local/node/bin/hexo"
cd /home/nodejs/blog/source/_posts/
refresh(){
git checkout master
git branch -D md
git pull
git checkout md
git pull
git merge master --no-edit
cd ../..
echo "$(date)" >> log.txt
hexo g
}
refresh
修改后的代码:
主要增加了脚本的类型,然后增加了环境变量,貌似node中调用的其他命令依赖了环境变量PATH。
#!/bin/bash
export PATH=/usr/local/bin:/usr/local/node/bin:$PATH
echo $PATH
alias node="/usr/local/node/bin/node"
alias hexo="/usr/local/node/bin/hexo"
cd /home/nodejs/blog/source/_posts/
refresh(){
git checkout master
git branch -D md
git pull
git checkout md
git pull
git merge master --no-edit
cd ../..
echo "$(date)" >> log.txt
hexo g
}
refresh