工作中我们常常需要在某些时候执行一些任务,Windows 下有定时任务管理, Linux 下则有 Crontab, 接触过 Linux 的童鞋一定不陌生。


Cron 是 Unix,Solaris, Linux 等系统下的可以自动在后台执行定时任务的工具,比如在某一天 9 点提醒你开会, 某一天 6 点去给女票买礼物等等, 这是由 cron 守护进程定期执行的。 如果启用了 cron(一般默认启用), cron 守护进程 会在系统启动后自动启动, 并按时执行任务。 cron 也能手动启用、关闭、重启等。

认识 crontab

Crontab 是 cron 的任务库文件,它存储了 cron 要执行的计划任务项目。 不同系统下该文件的位置可能不同。

  • macOS: /usr/lib/cron/tabs/
  • BSD Unix: /var/cron/tabs/
  • Solaris, Debian: /var/spool/cron/crontabs/
  • RHEL, CentOS, Fedora: /var/spool/cron/

cron 任务是一个包含特定日期,特定时间和要执行的命令的集合, 存储在 crontab 里。一个 crontab 条目如下图所示,指定了在每个月的所有周日凌晨 2 点 36 分 执行 /usr/local/sbin/ 下的 backup.sh 脚本。

Crontab 命令

crontab 命令很简单,

1
[root@localhost ~]$ crontab [-u username] [-l|-r|-e] [-n <host>|-c] [-s] [-x <mask>]

各选项含义如下:

  • -u: 指定 crontab 的用户名, 此选项只能 root 使用
  • -e: 编辑 crontab 文件, 如果没有,会新建一个
  • -l: 打印出 crontab 文件内容,列出计划任务
  • -r: 移出 crontab 文件
  • -n : 设定在 集群中的 host 主机上执行用户 crontabs
  • -c: 获取用户在集群上的 crontabs
  • -s: selinux 相关内容
  • -x : 开启 debug
    执行 crontab -e 后就会进入 crontab 编辑环境。
    1
    2
    3
    4
    5
    6
    7
    8
    # # 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
    | | | | |
    * * * * * command to be executed

时间格式为 min hour day_of_month month day_of_week, 每一项都是一定范围的整数或者数组或者范围。 一些辅助的字符有特别的意义。

特殊字符 代表含义
* 代表任何可能的值
, 代表分隔时段, 0 3,6 * * * command 表示在每天 3:00, 6:00 执行任务
- 代表时间范围, 0 10-20 * * * command 表示在每天10:00 到 20:00 执行任务
/n 代表 每隔 n 单位时间 重复一次

下面举几个 Crontab 的使用例子。

Crontab 例子

备份系统

每天 00:00 准时备份系统

1
0 0 * * * /usr/local/bin/backup.sh

会议提醒

提醒每周五下午 2:30 开会

1
20 14 * * 5 /path/to/alert.sh

记录 IP

每隔 3 小时记录 IP 并发送到指定邮箱

1
0 */3 * * * echo "$(date) : $(hostname -I)" | mutt -s "your ip" your_email_address > /dev/null

Crontab 使用补充

系统设定

如果你要做的是系统的例行性任务,则可以使用 /etc/crontab, 在里面加入你的定时任务就好。

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost ~]$ cat /etc/crontab
SHELL=/bin/bash <==使用哪種 shell 介面
PATH=/sbin:/bin:/usr/sbin:/usr/bin <==執行檔搜尋路徑
MAILTO=root <==若有額外STDOUT,以 email將資料送給誰

# 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

可以按照这个格式添加任务, 其中相对于 crontab -e, 多了一个 user-name, 即运行任务的用户。

系统资源

若定期运行的任务很多, 有时候会在某一时候运行很多任务, 系统资源会比较紧张,可以将任务分散开,使得系统负载相对平稳。

1
2
3
4
5
6
[root@localhost ~]$ cat /etc/crontab
0,5,10,15,20,25,30,35,40,45,50,55 * * * * root scripts_1.sh
1,6,11,16,21,26,31,36,41,46,51,56 * * * * root scripts_2.sh
2,7,12,17,22,27,32,37,42,47,52,57 * * * * root scripts_3.sh
3,8,13,18,23,28,33,38,43,48,53,58 * * * * root scripts_4.sh
4,9,14,19,24,29,34,39,44,49,54,59 * * * * root scripts_5.sh

使用限制

如果你的用户名在 /etc/cron.allow 中, 那是可以使用 crontab 的,但如果是在
/etc/cron.deny 中, 则无法使用并安排定时任务的。 /etc/cron.allow 的优先级高于 /etc/cron.deny

关闭邮件通知

cron 任务默认会在执行一个 cronjob 后发送一封邮件的,如果执行任务勤了,会产生大量的邮件。
如果输出不是必要的, 则可以通过在任务结尾加上重定向:

1
>/dev/null 2>&1

或者重定向到一个日志文件:

1
> /path/to/your/log/file 2>&1

环境变量

cron 会在用户 HOME 文件夹下执行命令,默认的环境变量有:

  • HOME=user-home-directory
  • LOGNAME=user-login-id
  • PATH=/usr/bin:/usr/sbin
  • SHELL=/usr/bin/sh
    要是你想要任务开始时执行 ~/.profile 里的命令, 需要显示地在脚本里执行 source ~/.profile

安全检测

有可能服务器会被人入侵,植入的木马一般都会以定时任务的形式运行,可以检查 /var/spool/cron/ 有没有问题。

周与日

day_of_monthday_of _week 一般不能同时设定,若同时设定了,系统会在所有符合一个或两个的日期都执行命令。

执行关机期间的任务

如果关机有任务没有执行, 开机后 cron 也不会执行过期的任务。想要执行过期任务,可以使用 anacron。 它作为定时会每小时被执行一次, 执行 cron 没有执行的任务。