Linux上使用crontab设置定时任务

简单介绍

很喜欢bing的首页图,想要实现一个简单的定时下载脚本,脚本使用python中的urllibre模块实现,因为都是内置模块,每个python环境都会包含。但是如何设置定时运行呢?网上搜索得知,可以使用crontab来制定定时任务。这里简单记录其用法,之后会写个帖子记录下这次经历。


在介绍crontab命令之前,我们首先要介绍一下crond,因为crontab命令需要crond服务支持。crond是Linux下用来周期地执行某种任务或等待处理某些事件的一个守护进程,和Windows中的计划任务有些类似。

crond 服务的启动和自启动方法如下:

  1. $ service crond restart
  2. 停止 crond [确定]
  3. 正在启动 crond [确定]
  4. #重新启动crond服务
  5. $ chkconfig crond on
  6. #设定crond服务为开机自启动

其实,在安装完成操作系统后,默认会安装crond服务工具,且crond服务默认就是自启动的。crond进程每分钟会定期检查是否有要执行的任务,如果有,则会自动执行该任务。

最后,请保证需要执行的这条指令单独是可以运行并实现你的目标的,并且没有副作用。

选项

usage:    crontab [-u user] file
    crontab [ -u user ] [ -i ] { -e | -l | -r }
        (default operation is replace, per 1003.2)
    -e    (edit user's crontab)
    -l    (list user's crontab)
    -r    (delete user's crontab)
    -i    (prompt before deleting user's crontab)

crontab -e编辑完成之后,一旦保存退出,那么这个定时任务实际就会写入/var/spool/cron/目录中,每个用户的定时任务用自己的用户名进行区分。而且crontab命令只要保存就会生效,只要crond服务是启动的。

语法

Schedule cron jobs to run on a time interval for the current user.

Linux上使用`crontab`设置定时任务 - 图1

Job definition format: (min) (hour) (day_of_month) (month) (day_of_week) command_to_execute.(用空格隔开)

书写时,有一些特殊符号有自己的含义,可以适当使用来灵活设定时间:

特殊符号 含义
* 代表任何时间。比如第一个”*”就代表一小时种每分钟都执行一次的意思。
, 代表不连续的时间。比如”0 8,12,16*命令”就代表在每天的 8 点 0 分、12 点 0 分、16 点 0 分都执行一次命令。
- 代表连续的时间范围。比如”0 5 ** 1-6命令”,代表在周一到周六的凌晨 5 点 0 分执行命令。
/ 代表每隔多久执行一次。比如”*/10命令”,代表每隔 10 分钟就执行一次命令。

来自http://c.biancheng.net/view/1092.html的几个例子:

时间指令 含义
45 22 *命令 在 22 点 45 分执行命令
0 17 ** 1命令 在每周一的 17 点 0 分执行命令
0 5 1,15**命令 在每月 1 日和 15 日的凌晨 5 点 0 分执行命令
40 4 ** 1-5命令 在每周一到周五的凌晨 4 点 40 分执行命令
*/10 4 命令 在每天的凌晨 4 点,每隔 10 分钟执行一次命令
0 0 1,15 * 1命令 在每月 1 日和 15 日,每周一个 0 点 0 分都会执行命令,注意:星期几和几日最好不要同时出现,因为它们定义的都是天,非常容易让管理员混淆

简单实例

来自tldr的例子:

# Edit the crontab file for the current user:
crontab -e

# Edit the crontab file for a specific user:
sudo crontab -e -u user
# View a list of existing cron jobs for current user:
crontab -l
# Remove all cron jobs for the current user:
crontab -r

# 下面这些
# Sample job which runs at 10:00 every day (* means any value):
0 10 * * * command_to_execute
# Sample job which runs every minute on the 3rd of April:
* * 3 Apr * command_to_execute
# Sample job which runs a certain script at 02:30 every Friday:
30 2 * * Fri /absolute/path/to/script.sh

来自http://c.biancheng.net/view/1092.html的几个例子:

在“执行的任务”字段中既可以定时执行系统命令,也可以定时执行某个 Shell 脚本,这里举几个实际的例子。

首先crontab -e进入编辑界面:

让系统每隔 5 分钟就向/tmp/test文件中写入一行“11”,验证一下系统定时任务是否会执行。

*/5 * * * * /bin/echo "11" >> /tmp/test

这个任务在时间工作中没有任何意义,但是可以很简单地验证我们的定时任务是否可以正常执行。如果觉得每隔 5 分钟太长,那就换成“”,让它每分钟执行一次。而且和at命令一样,*如果我们定时执行的是系统命令,那么最好使用绝对路径

让系统在每周二的凌晨 5 点 05 分重启一次。

5.5 * * 2 /sbin/shutdown -r now

如果服务器的负载压力比较大,则建议每周重启一次,让系统状态归零。比如绝大多数游戏服务器每周维护一次,维护时最主要的工作就是重启,让系统状态归零。这时可以让我们的服务器自动来定时执行。

在每月 1 日、10 日、15 日的凌晨 3 点 30 分都定时执行日志备份脚本 autobak.sh。

30.3 1,10,15 * * /root/sh/autobak.sh

这些定时任务保存之后,就可以在指定的时间执行了。

我们可以使用命令crontab -lcrontab -r来查看和删除当前用户设置的定时任务,其中如果只想删除某个定时任务,则可以执行crontab -e命令进入编辑模式手工删除。

在书写crontab定时任务时,需要注意以下几个事项:

  • 6 个选项都不能为空,必须填写。如果不确定,则使用“*”代表任意时间。
  • crontab 定时任务的最小有效时间是分钟,最大有效时间是月。像 2018 年某时执行、3 点 30 分 30 秒这样的时间都不能被识别。
  • 在定义时间时,日期和星期最好不要在一条定时任务中出现,因为它们都以天为单位,非常容易让管理员混淆。
  • 在定时任务中,不管是直接写命令,还是在脚本中写命令,最好都使用绝对路径。有时使用相对路径的命令会报错。

:::info 一般第一次使用crontab -e的时候,执行crontab会要求你设置编辑器,如果选的不合适,可以退出后重新执行select-editor重新选择。 :::

crontab开启日志

由于Ubuntu默认没有开启crontab的日志记录,所以对于crontab的执行情况是看不到的。为了开启这个,我们可以编辑/etc/rsyslog.d/50-default.conf文件,将cron.* /var/log/cron.log这一句对应的注释去掉。重启服务即可。主要指令如下:

sudo vim /etc/rsyslog.d/50-default.conf
cron.*  /var/log/cron.log #将cron前面的注释符去掉
#重启rsyslog
sudo service rsyslog restart
sudo service cron restart

这样就可以用tail -f /var/log/cron.log查看日志了。

在线书写任务

image.png

参考链接