前言
这是一篇丢失在时间长河又突然回归的文章,被scp基金会在几个月前收容,又在2020年10月14日确认无危险性,因此回归本公众号。
参考文档:
- 1、【Linux定时任务Crontab命令详解】https://www.cnblogs.com/intval/p/5763929.html
- 2、【Linux crontab命令详解】https://www.cnblogs.com/ftl1012/p/crontab.html
- 3、【Linux crontab 命令】https://www.runoob.com/linux/linux-comm-crontab.html
- 4、【在线工具】https://tool.lu/crontab/
正文
怎么在Linux下定时启动某个任务?
例如自动备份mysql数据库,每天更新外部接口数据?
在Linux下有个与windows下的计划任务类似的工具,即crond。
crond 是linux下一般默认安装并自启动的服务工具,crond进程每分钟会定期检查是否有要执行的任务,如果有要执行的任务,则自动执行该任务。
如果你的Linux系统中没有此服务,可以安装一下。
yum install crontabs
在Linux下的任务调度分为两类,系统任务调度和用户任务调度。
系统任务调度:系统周期性所要执行的工作,比如写缓存数据到硬盘、日志清理等。在/etc目录下有一个crontab文件,这个就是系统任务调度的配置文件。
用户任务调度:用户定期要执行的工作,比如用户数据备份、定时邮件提醒等。所有用户定义的crontab 文件都被保存在 /var/spool/cron目录中。其文件名与用户名一致。
而使用crond的控制命令则是crontab
。
什么是crontab?
首先看下cronttab的使用说明
[root@localhost ~]# crontab --help
crontab:无效选项 -- -
crontab: usage error: unrecognized option
Usage:
crontab [options] file
crontab [options]
crontab -n [hostname]
Options:
-u <user> define user
-e edit user's crontab
-l list user's crontab
-r delete user's crontab
-i prompt before deleting
-n <host> set host in cluster to run users' crontabs
-c get host in cluster to run users' crontabs
-s selinux context
-x <mask> enable debugging
Default operation is replace, per 1003.2
crontab 是用来让使用者在固定时间或固定间隔执行程序之用,换句话说,也就是类似使用者的时程表。
常用参数 | 说明 |
---|---|
-u user | 是指设定指定 user 的时程表,这个前提是你必须要有其权限(比如说是 root)才能够指定他人的时程表。如果不使用 -u user 的话,就是表示设定自己的时程表。 |
-e | 执行文字编辑器来设定时程表,内定的文字编辑器是 VI,如果你想用别的文字编辑器,则请先设定 VISUAL 环境变数来指定使用那个文字编辑器(比如说 setenv VISUAL joe) |
-r | 删除目前的时程表 |
-l | 列出目前的时程表 |
查看下/etc/crontab
文件,内容如下:
[root@izbp117mtgmllet9ryobawz ~]# cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59) 分钟
# | .------------- hour (0 - 23) 小时
# | | .---------- day of month (1 - 31) 一个月中的第几天
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ... 月份
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat 星期
# | | | | |
# * * * * * user-name command to be executed
- 第一行SHELL变量指定了系统要使用哪个shell,这里是bash;
- 第二行PATH变量指定了系统执行命令的路径;
- 第三行MAILTO变量指定了crond的任务执行信息将通过电子邮件发送给root用户,如果MAILTO变量的值为空,则表示不发送任务执行信息给用户。
- 星号(*):代表所有可能的值,如month字段为星号,则表示在满足其它字段的制约条件后每月都执行该命令操作。
- 逗号(,):可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”
- 连字符(-):连字符定义范围。例如,2000-2010 表示2000年至2010年期间的每年,包括2000年和2010年。
- 正斜线(/):可以用正斜线指定时间的间隔频率,例如“0-23/2”表示每两小时执行一次。
小 结:
- 周和日最好不要同时用
- 定时任务要加注解
- 可以定向到日志文件或者空文件
- 定时任务一定是绝对路径,且目录必须存在才能出结果
- crontab 服务一定要开启运行
cron表达式工具
我们有时很容易记错或弄混crontab的表达式,这时我们可以借助工具来进行验证。
如每隔12小时执行一次任务:
0 */12 * * *
接下来7次的执行时间:
2020-10-14 12:00:00
2020-10-15 00:00:00
2020-10-15 12:00:00
2020-10-16 00:00:00
2020-10-16 12:00:00
2020-10-17 00:00:00
2020-10-17 12:00:00
添加cron任务
crontab -e
使用此命令会直接打开/var/spool/cron/
下与用户名相同的文件,如是root,就相当于
vim /var/spool/cron/root
添加cron任务,编辑内容,按i
插入(其实就是使用vi来操作文本)。
0-59/2 * * * * ls /home > home.log
:wq
保存。
等同于下面这个命令
echo "*/2 * * * * ls /home > home.log" >> /var/spool/cron/root
添加完crontab任务后,可使用下面命令查看任务是否添加成功
crontab -l
重启crond
生效
systemctl restart crond
查看服务运行情况
systemctl status crond
等了一分钟,发现任务没有运行,我以为home.log
会出现在/var/spool/cron
目录下
查看下cron的运行情况
cat /var/log/cron
或
tail -fn100 /var/log/cron
/var/log/cron
记录了所有cron的运行记录
查看信息如下
Oct 14 10:38:01 mail CROND[25295]: (root) CMD (ls /home > home.log)
You have new mail in /var/spool/mail/root
修改crontab任务
crontab -e # 打开/var/spool/cron/root 文件
# 编辑
0-59/2 * * * * ls /home > /var/log/home.log
crontab -l # 查看
systemctl restart crond # 重启定时任务管理器,立即生效
观察cron记录,tail -fn100 /var/log/cron
,发现执行
Oct 14 10:46:55 mail crond[29898]: (CRON) INFO (running with inotify support)
Oct 14 10:46:55 mail crond[29898]: (CRON) INFO (@reboot jobs will be run at computer's startup.)
Oct 14 10:47:01 mail CROND[29956]: (root) CMD (/usr/bin/ls /home > /var/log/home.log)
再查看日志,果然已经有了内容
cat /var/log/home.log
其他cron实例参考
意思是每两个小时重启一次apache
0 */2 * * * /sbin/service httpd restart
每天22:50关闭ssh服务
50 22 * * * /sbin/service sshd stop
每天7:50开启ssh服务
50 7 * * * /sbin/service sshd start
每月1号和15号检查/home 磁盘
0 0 1,15 * * /usr/sbin/fsck /home
每小时的第一分执行 /home/bruce/backup这个文件
1 * * * * /home/bruce/backup
每周一至周五3点钟,在目录/home中,查找文件名为*.xxx的文件,并删除4天前的文件。
00 03 * * 1-5 find /home "*.log" -mtime +4 -exec rm {} \;
每月的1、11、21、31日是的6:30执行一次ls命令
30 6 */10 * * ls
FAQ
如果我们使用 crontab 来定时执行脚本,无法执行,但是如果直接通过命令(如:./test.sh)又可以正常执行,这主要是因为无法读取环境变量的原因。
解决方法:
1、所有命令需要写成绝对路径形式,如:
/usr/local/bin/docker。
2、在 shell 脚本开头使用以下代码:
#!/bin/bash
source /etc/profile
source ~/.bash_profile
3、在 /etc/crontab 中添加环境变量,在可执行命令之前添加命令
. /etc/profile;/bin/sh
使得环境变量生效,例如:
20 03 * * * . /etc/profile;/bin/sh /var/www/runoob/test.sh
注意事项
1、新创建的 cron 任务,不会马上执行,至少要过 2 分钟后才可以,当然你可以重启 cron 来马上执行。
2、当crontab突然失效时,可以尝试/etc/init.d/crond restart解决问题。或者查看日志看某个job有没有执行/报错tail -f /var/log/cron。
3、千万别乱运行crontab -r。它从Crontab目录(/var/spool/cron)中删除用户的Crontab文件。删除了该用户的所有crontab都没了。
4、在crontab中%是有特殊含义的,表示换行的意思。如果要用的话必须进行转义%,如经常用的date ‘+%Y%m%d’在crontab里是不会执行的,应该换成date ‘+%Y%m%d’。