linux之crontab定时任务

Linux crontab 命令

Linux crontab 是用来定期执行程序的命令。

当安装完成操作系统之后,默认便会启动此任务调度命令。

crond 命令每分钟会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。

注意:新创建的 cron 任务,不会马上执行,至少要过 2 分钟后才可以,当然你可以重启 cron 来马上执行。

而 linux 任务调度的工作主要分为以下两类:

  • 1、系统执行的工作:系统周期性所要执行的工作,如备份系统数据、清理缓存
  • 2、个人执行的工作:某个用户定期要做的工作,例如每隔 10 分钟检查邮件服务器是否有新信,这些工作可由每个用户自行设置

/etc/crontab文件中可以看到所有用户的crontab任务,我自己实测直接修改/etc/crontab来添加crontab任务没有生效(可能是权限问题,我没深究),所以没有修改该文件来创建crontab任务

/etc/cron.deny #该文件中所列的用户不允许使用Crontab命令

/etc/cron.allow #该文件中所列的用户允许使用Crontab命令

crontab命令格式详解

每项工作 (每行) 的格式都是具有六个栏位,这六个栏位的意义为:

代表意义 分钟 小时 日期(天) 月份 命令
数字范围 0-59 0-23 1-31 1-12 0-7 呀就命令啊
1
crontab -u {username} -e  #不加-u参数默认为当前用户创建定时任务

输入命令后会显示编辑一个文件,直接在下面添加参数,username可以不加,则默认给当前用户添加定时任务

1
2
3
4
5
6
7
8
*    *    *    *    * {username} 命令/要执行shell脚本的路径
- - - - -
| | | | |
| | | | +----- 星期中星期几 (0 - 6) (星期天 为0)
| | | +---------- 月份 (1 - 12)
| | +--------------- 一个月中的第几天 (1 - 31)
| +-------------------- 小时 (0 - 23)
+------------------------- 分钟 (0 - 59)

修改定时任务crontab -e的时候,控制台输出“crontab: installing new crontab”,表示任务添加成功,且之后三分钟不会执行对应的任务,所以在调试定时器的时候,要把这三分钟考虑进去,如果执行的时间在三分钟内的话,对应的任务则不会生效。

定时执行命令

例如安装的Tomcat服务器需要每次开机后都要重启一次

1
2
3
4
5
#在crontab -e命令后添加的参数

#系统重启后执行重启
@reboot systemctl restart tomcat
# @reboot [nohup] systemctl restart tomcat

nohup 是用来让运行的程序忽略 SIGHUP 指令(因为在父程序退出后,所有的子程序会受到 SIGHUP 指令)从而保证运行的程序不退出, 根据实际情况决定是否使用该参数(本人实际操作过程中,加入该参数时无法成功执行任务,请自测)
@reboot 只针对可登录服务器的用户生效, 如果使用不可登录服务器的用户执行该类型crontab任务,将会遭到忽略,执行失败

定时关机

1
2
3
4
#每天 23:00 关机
* 23 * * * root /sbin/shutdown -h now
#每天 23:00 十分钟后关机
* 23 * * * root /sbin/shutdown -h at 23:10

因为直接crontab来执行命令,可能有些命令太复杂或者太长可能会执行失败,这时候就会用到shell脚本

定时执行shell脚本

执行时间 格式
每分钟定时执行一次 * * * * *
每小时定时执行一次 0 * * * *
每天定时执行一次 0 0 * * *
每周定时执行一次 0 0 * * 0
每月定时执行一次 0 0 1 * *
每月最后一天定时执行一次 0 0 L * *
每年定时执行一次 0 0 1 1 *
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#在crontab -e命令后添加的参数


#每天 02:00 执行任务
0 2 * * * /bin/sh backup.sh

#每天 5:00和17:00执行任务
0 5,17 * * * /scripts/script.sh

#每分钟执行一次任务
* * * * * /scripts/script.sh

#每周日 17:00 执行任务
0 17 * * 7 /scripts/script.sh

#每 10min 执行一次任务
*/10 * * * * /scripts/monitor.sh

#在每周五、周日的17点执行任务
0 17 * * sun,fri /script/scripy.sh

#每四个小时执行一个任务
0 */4 * * * /scripts/script.sh

#每周一、周日的4:00和17:00执行任务
0 4,17 * * sun,mon /scripts/script.sh

比较有趣的是那个『周』喔!周的数字为0或7时,都代表『星期天』的意思!另外, 还有一些辅助的字符,大概有底下这些:

特殊字符 代表意义
*(星号) 代表任何时刻都接受的意思!举例来说,范例一内那个日、月、周都是 * , 就代表著『不论何月、何日的礼拜几的 12:00 都运行后续命令』的意思!
,(逗号) 代表分隔时段的意思。举例来说,如果要下达的工作是 3:00 与 6:00 时,就会是: 0 3,6 * * * command 时间参数还是有五栏,不过第二栏是 3,6 ,代表 3 与 6 都适用!
-(减号) 代表一段时间范围内,举例来说, 8 点到 12 点之间的每小时的 20 分都进行一项工作: 20 8-12 * * * command 仔细看到第二栏变成 8-12 喔!代表 8,9,10,11,12 都适用的意思!
/n(斜线) 那个 n 代表数字,亦即是『每隔 n 单位间隔』的意思,例如每五分钟进行一次,则: */5 * * * * command 很简单吧!用 * 与 /5 来搭配,也可以写成 0-59/5 ,相同意思!

周与日月不可同时并存

另一个需要注意的地方在於:『你可以分别以周或者是日月为单位作为循环,但你不可使用「几月几号且为星期几」的模式工作』。 这个意思是说,你不可以这样编写一个工作排程:

1
30 12 11 9 5 root echo "just test"  <==这是错误的写法

本来你以为九月十一号且为星期五才会进行这项工作,无奈的是,系统可能会判定每个星期五作一次,或每年的 9 月 11 号分别进行,如此一来与你当初的规划就不一样了~所以罗,得要注意这个地方!上述的写法是不对的!

使crontab任务生效

1
2
3
4
5
#查看crontab任务
crontab -l

#加载配置文件
/etc/init.d/cron reload

centos的定时任务service是crond

脚本无法执行问题

如果我们使用 crontab 来定时执行脚本,无法执行,但是如果直接通过命令(如:./test.sh)又可以正常执行,这主要是因为无法读取环境变量的原因。

解决方法:

  • 1、所有命令需要写成绝对路径形式,如: /usr/local/bin/docker。

  • 2、在 shell 脚本开头使用以下代码:

    1
    2
    3
    4
    #!/bin/bash

    . /etc/profile
    . ~/.bashrc
  • 3、在 /etc/crontab 中添加环境变量,在可执行命令之前添加命令 . /etc/profile;/bin/sh,使得环境变量生效,例如:

    1
    20 03 * * * . /etc/profile;/bin/sh /var/www/runoob/test.sh