0、前言
cron 是一个调度守护进程,它以指定的时间间隔执行任务,这些任务称为 cron 作业,主要用于自动执行系统维护或管理任务。例如,你可以设置一个 cron 作业来自动执行重复的任务,比如备份数据库或数据,使用最新的安全补丁更新系统,检查磁盘空间使用情况,发送电子邮件等等。
——Linux中国(使用 cron 调度任务)
cron 有 cron.service 和 crontab 两个概念。
cron.service 是后台守护进程的名称,用来实际执行脚本,启动后,它在系统中是一直运行的。(有的系统中叫 crond.service )
crontab 是一个工具(缩写自:cron table),它是cron的配置,也可以叫它作业列表,用来管理定时任务列表,比如添加作业、编辑作业、删除作业、查看作业。
cron的任务执行时间精确度是到分钟。(实际上也就是意味着,cron.service每分钟都会检查一下看看有无要执行的任务,有的话就自动执行任务)
本文实践基于:Ubuntu 22.04.1 LTS
使用SSH连接工具:OpenSSH Client
使用账号:root
注:以下命令,如果是 CentOS 则要把 cron 全都改为 crond。
1、检查cron.service有无启动
查看 cron.service 的状态,方式一:systemctl status cron.service
正常结果:
服务已启动
查看 cron.service 的状态,方式二:service cron status
正常结果:
服务已启动
active(running) 表示 cron.service 正在执行
可能报错:Unit cron.service could not be found.
可能原因1:Ubuntu 里面叫 cron.service,CentOS里叫 crond.service
解决:
Ubuntu里用 systemctl status cron.service
CentOS里用 systemctl status crond.service
可能原因2:没安装cron
注:不过实践下来操作系统基本都自带了cron,没见过没有安装的
检查:
Linux因为安装软件的方式多种多样,实在是不好检查一个软件是否真的没安装。
可能是用rpm安装的(检查命令:rpm -qa|grep cron)
可能是用apt安装的(检查命令:apt list --installed|grep cron)
源码编译安装的等等。
还可以检查一下相关文件是否存在,比如用 whereis cron
注意:如果rpm等都没安装,则基本可以排除用对应方式安装的可能。
安装:apt install cron
(未测试,因为实践的环境已经安装有了,就没去动)
其他命令:
服务处于关闭状态
如果服务不是 active,则需要启动,启动命令:service cron start
关闭命令:service cron stop
重启命令:service cron restart
重新加载配置:service cron reload
注意服务运行中时的Unit描述内容里的的二行: Loaded:loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enabled)
Loaded 描述的是操作系统启动时会不会启动这个服务。
enabled 表示开机时启动,disabled 表示开机时不启动。
启动该服务的配置文件路径为:/lib/systemd/system/cron.service
vendor preset 为 Linux发行版 默认配置,是在Linux 发行制作过程预设的,一般一些重要的系统服务会配置为enabled。使用 systemctl enable/disable 来设置为开机自启动,并没有设置到操作系统的发行预设里,所以进行设置开机启动项的时候,不会影响到 vendor preset 的值。 如果是同一名称的服务(例如现在这个cron.service),既使用了 systemctl enable,又配置了vendor preset,systemctl enable/disable 的优先级要高于vendor preset(毕竟 systemctl 相当于是用户手动设置)。
如果要禁止 cron.service 开机自启动,则可以执行命令:systemctl disable cron.service
如果要设置 cron.service 开机自启动,则可以执行命令:systemctl enable cron.service
(这里的操作和概念,其实也适用于其他服务)
2、编写定时任务要执行的命令
通常情况下,我们会把要执行的命令写成一个脚本(比如 shell脚本、python脚本)。
脚本的内容依据你实际情况来写,本文仅作示例。
下图为我写的一个shell脚本示例,目的是:先打印一下时间,然后ping百度,最后来一个换行。
执行结果如图所示:
此时,我们要获取一下这个shell脚本的绝对路径,留作备用(需先进入脚本所在目录)
执行命令:realpath 脚本文件名
此时,我们得到了脚本的绝对路径:/apps/crons/pingCron.sh
3、配置定时任务
配置定时任务有两种方式,一种是直接修改cron的配置文件,一种是通过crontab间接修改cron的配置文件。
通常不建议直接编辑配置文件,推荐使用crontab来操作。
注意:cron服务运行时会不断检查配置文件,所编辑配置文件以后,不需要重启cron或者重新加载配置文件。
crontab的一些命令:
列出当前的定时任务表命令:crontab -l
执行编辑器来设定定时任务表命令:crontab -e
(有的系统/版本会默认使用vim作为编辑器,有的会让你选一个编辑器)
选择编辑器(选了2)
删除目前所有的定时任务命令:crontab -r
给某个用户设置定制任务命令:crontab -u username { -l | -e | -r }
示例
(其实这个命令就是多了一个 -u username,后面跟着的就是前面照常的其他命令)
(不加 -u username,就是设置自己的定时任务)
(当前登录账号需要有这个被设置定时任务的用户的权限)
具体定时任务的设置:
说明和示例
可以先看上图中官方提供的说明。
然后再看我标出来的最后一行,也就是我写的一个定时任务设置。
时间的具体格式如下图所示:
图源自菜鸟教程(文末有链接)
星号表示该项全部适配,例如每分钟都执行,每小时都执行。
时间后面跟着的,就是你要做什么事情。比如我写的这个示例就是执行shell脚本(建议要执行的脚本等文件都写绝对路径)。
注意一个任务写一行。
下面有一些示例:
每分钟执行一次输出:
* * * * * echo "abc"
每两分钟执行一次shell脚本:
*/2 * * * * /bin/sh /apps/crons/pingCron.sh
(/表示频率)
每月1到3号的8点30分执行shell脚本:
30 8 1-3 * * /bin/sh /apps/crons/pingCron.sh
(-表示区间)
每小时的15分和30分执行shell脚本:
15,30 * * * * /bin/sh /apps/crons/pingCron.sh
(,表示并列)
cron定时任务的执行日志,默认是输出到 /var/log 文件夹中的一个文件或文件夹里,可能是叫 cron.log(不同系统可能不太一样,但是重点还是找 cron 这个关键词)
Ubuntu系统默认情况下不生成cron日志文件,所以,需要进行配置。(其他系统未必需要配置)
执行命令:vi /etc/rsyslog.d/50-default.conf
找到 cron.* 这一行,去掉前面的 #
去掉注释后的效果
注意保存修改内容,然后退出文本编辑。
重启系统日志服务:service rsyslog restart
此时,只要你有定时任务执行,则就会生成对应的cron日志文件。
日志内容示例
实际上,你会发现,这里的日志,只记录了有没有执行某个任务,没记录任务执行的输出内容。
如果你要看任务执行的输出内容,其实最好的方式就是输出重定向(见下文)。
注:我有看到菜鸟教程里说 “新创建的 cron 任务,不会马上执行,至少要过 2 分钟后才可以,可以重启 cron 来马上执行”,这一点我在本文的环境下实测发现新建的任务是能立即检测到,并在下一个分钟到达时立即执行的,不需要等待。可能是不同系统或者版本差异?这一点存疑。(另外,我也没有在其他地方看到有关描述,不知道这个说法的来源是哪里)(若读者知晓,请在评论区解答一下,谢谢!)
注:我看不少教程里,都是设置定时任务时,可以加上用户名,以表示是哪个用户的定时任务。但是我这个版本实测并不行,不知道为啥以及什么版本才支持。(若读者知晓,请在评论区解答一下,谢谢!)
带用户名的格式是:
* * * * * username command
4、任务执行输出重定向
* * * * * /bin/sh /apps/crons/pingCron.sh >> /apps/crons/ping.log 2>&1
只需要在设置定时任务的时候,加上后面这一段就行了。
>> 表示输出追加到某个文件(> 是输出时覆盖原文件内容)
/apps/crons/ping.log 表示自定义的日志输出路径(文件不存在会自动创建)
2>&1 表示把标准错误流也重定向到指定的日志文件中
重定向有个好处就是任务执行的完整信息可以相对独立地在一个日志文件中进行展示。
重定向的日志记录示例
注意:如果配置有误,执行日志可能不会输出到重定向的日志文件中,此时日志就会输出到上文提及的默认的日志输出文件中。
5、利用cron在系统启动时执行特定脚本
执行定时任务设置:crontab -e
设置启动时执行脚本:@reboot command
例如:我现在有一个脚本 run-on-boot.sh,里面执行的是——打印一些文字。
脚本内容
利用 crontab -e 设置任务并将输出重定向:@reboot /bin/sh /apps/crons/run-on-boot.sh >> /apps/crons/run-on-boot.log 2>&1
重启系统:reboot
输出日志: