Linux中的crontab定时任务(非常详细)
顾名思义,定时任务就是指定一个时间或者一个周期让 Linux 操作系统自动完成一系列的任务。
Linux 运维工程师在企业中的很多操作都是靠 Shell 脚本来完成的,特别是一些重复性的简单操作。例如,清理日志文件、系统信息采集、同步时间和备份重要文件等。这些任务并不是做一次就完事,每天或每周都要去做,那就需要学习本节的定时任务配合完成工作。
定时任务类似于我们平时生活中的闹钟,定点去工作。工作的内容主要是一些周期性的任务,比如晚上 11 点备份数据、凌晨 0 点清理日志文件、凌晨 1 点同步各个服务器之间的时间等。
在介绍 crontab 命令之前,要先介绍 crond。为什么呢?因为 crontab 命令得依靠 crond 服务支持。
crontab 是一个工具,专门用来配置各种定时任务,具体去实现这些任务的是 crond 服务。
crond 服务的启动和自启动方法如下:
在操作系统安装完成后,默认就会安装 crond 服务和 crontab 工具,crond 服务默认是开机自启动的。若两者都不存在的话,可以通过 DNF 命令来安装部署:
注意,Linux 操作系统中默认只存在 /etc/cron.deny 文件,/etc/cron.allow 文件需自行创建。所有用户通过 crontab 命令配置定时任务时,配置文件默认都存放在 /var/spool/cron中,文件名以用户名命名。
在 Linux 操作系统中,每个用户都可以实现自己独有的 crontab 定时任务,只需要使用用户身份执行 crontab -e 命令即可。当然,写入到 /etc/cron.deny 文件中的用户不能执行此命令。
crontab 命令的语法格式如下:
用户只需要执行 crontab -e 命令,系统会自动调用文本编辑器(默认为 Vim 编辑器)并打开文件 /var/spool/cron/ 用户名,无须手动指定任务列表中文件的位置。
当用户执行 crontab -e 命令配置定时任务时,会发现初次打开的是一个空文件,这个空文件也有固定的语法格式,需要按照固定的格式配置定时任务。
使用 crontab 命令配置定时任务的语法格式如下:
总共有 6 个字段,前 5 个字段用来指定任务重复执行的时间规律,第 6 个字段用于指定具体的任务内容。在 crontab 任务配置记录中,所设置的命令在“分钟+小时+日期+月份+星期”都满足的条件下才会执行。
时间周期的设置除了使用整数之外,还有一些特殊的符号表示方法:
这里列举几个例子帮助大家理解这些特殊的符号表示方法:
到这里大家应该对前 5 个时间字段非常熟悉了,那第 6 个字段呢?第 6 个字段既可以配置定时执行系统命令,也可以配置定时执行某个 Shell 脚本,我们通过几个案例演示一下。
【实例】每天凌晨 1:50 停止 sshd 服务,防止员工远程登录服务器,到早上 7:50 再启动 sshd 服务,让员工可以登录服务器进行工作。
【实例】每 3 分钟备份一次 /etc/passwd 文件,并将备份的文件备注上时间日期。
【实例】每 3 分钟执行一次 Shell 脚本。
【实例】使用普通用户配置定时任务。
既然有用户级别的定时任务,必然也会存在系统级别的定时任务。系统级别的定时任务需要用到配置文件 /etc/crontab。
不知道大家有没有注意到,在上文使用 crontab 命令配置定时任务时并没有指定用户,这是因为在通过 crontab -e 命令配置定时任务时,默认使用的身份是当前登录用户。而在通过修改 /etc/crontab 配置文件执行定时任务时,定时任务的执行者身份是可以手动指定的。这使得定时任务的执行变得更加灵活,修改起来也更加方便。
打开配置文件 /etc/crontab:
我们将之前演示过的那些定时任务配置到 /etc/crontab 文件中,其实效果都是一样的,只不过多了表示用户身份的字段,示例如下:
由示例可见,通过 crontab 命令和通过配置文件配置的定时任务之间是互不影响的,而且在 /etc/crontab 配置文件中配置的定时任务并不会通过 crontab 命令展示出来。
Linux 运维工程师在企业中的很多操作都是靠 Shell 脚本来完成的,特别是一些重复性的简单操作。例如,清理日志文件、系统信息采集、同步时间和备份重要文件等。这些任务并不是做一次就完事,每天或每周都要去做,那就需要学习本节的定时任务配合完成工作。
定时任务类似于我们平时生活中的闹钟,定点去工作。工作的内容主要是一些周期性的任务,比如晚上 11 点备份数据、凌晨 0 点清理日志文件、凌晨 1 点同步各个服务器之间的时间等。
Linux用户级别的定时任务
在 Linux 操作系统中若想使用定时任务,就需要掌握 crontab 命令,这条命令专门用来设置周期性执行的任务。在介绍 crontab 命令之前,要先介绍 crond。为什么呢?因为 crontab 命令得依靠 crond 服务支持。
crond 是 Linux 操作系统中用来周期性执行某种任务或等待处理任务的一个守护进程。
这样解释属实有些官方,通俗一些说,crond 是一个服务,当这个服务启动后它会一直在后台运行,那这个服务是怎么工作的呢?需要使用 crontab 命令进行配置,crontab 会命令 crond:“每天晚上 11 点让某个 Shell 脚本执行一下”,或者命令 crond:“每周三中午 12 点执行一下某条命令”……crontab 是一个工具,专门用来配置各种定时任务,具体去实现这些任务的是 crond 服务。
crond 服务的启动和自启动方法如下:
[root@linux mnt]# systemctl start crond #启动 crond 服务 [root@linux mnt]# systemctl enable crond #设为开机自启动 [root@linux mnt]# ps -ef | grep crond #查询 crond 服务是否已启动 root 1344 1 0 10:27 ? 00:00:00 /usr/sbin/crond -n [root@linux mnt]# systemctl status crontab #查看 crond 服务的状态 Unit crontab.service could not be found. [root@linux mnt]# systemctl status crond ● crond.service - Command Scheduler Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2024-12-05 10:27:48 CST; 11h ago Main PID: 1344 (crond) Tasks: 1 (limit: 23376) Memory: 1.6M CGroup: /system.slice/crond.service └─1344 /usr/sbin/crond -ncrond 服务每分钟都会检查是否有要执行的任务,如果有则会自动执行该任务。
在操作系统安装完成后,默认就会安装 crond 服务和 crontab 工具,crond 服务默认是开机自启动的。若两者都不存在的话,可以通过 DNF 命令来安装部署:
dnf -y install crontabs
启用周期性任务有一个前提条件,即对应的系统服务 crond 服务必须已经运行。我们可以通过 /etc/cron.allow 和 /etc/cron.deny 这两个文件来控制用户是否可以使用 crontab 命令,控制方法也非常简单:- /etc/cron.allow:只有写入此文件的用户可以使用 crontab 命令,没有写入的用户不能使用 crontab 命令。优先级最高。
- /etc/cron.deny:写入此文件的用户不能使用 crontab 命令,没有写入文件的用户可以使用 crontab 命令。
注意,Linux 操作系统中默认只存在 /etc/cron.deny 文件,/etc/cron.allow 文件需自行创建。所有用户通过 crontab 命令配置定时任务时,配置文件默认都存放在 /var/spool/cron中,文件名以用户名命名。
在 Linux 操作系统中,每个用户都可以实现自己独有的 crontab 定时任务,只需要使用用户身份执行 crontab -e 命令即可。当然,写入到 /etc/cron.deny 文件中的用户不能执行此命令。
crontab 命令的语法格式如下:
crontab -e [-u 用户名] crontab -l [-u 用户名] crontab -r [-u 用户名]上述命令分别表示编辑计划任务、查看计划任务和删除计划任务。root 用户可以管理普通用户的计划任务,普通用户只能管理自己的计划任务。
用户只需要执行 crontab -e 命令,系统会自动调用文本编辑器(默认为 Vim 编辑器)并打开文件 /var/spool/cron/ 用户名,无须手动指定任务列表中文件的位置。
当用户执行 crontab -e 命令配置定时任务时,会发现初次打开的是一个空文件,这个空文件也有固定的语法格式,需要按照固定的格式配置定时任务。
[root@linux mnt]# crontab -e 50 1 * * * systemctl stop sshd 50 7 * * * systemctl start sshd
使用 crontab 命令配置定时任务的语法格式如下:
时间周期设置: 任务内容设置: 50 3 2 1 * run_command 分钟 小时 日期 月份 星期 要执行的命令各参数的含义如下:
- 分钟:取值为从 0 到 59 之间的任意整数;
- 小时:取值为从 0 到 23 之间的任意整数;
- 日期:取值为从 1 到 31 之间的任意整数;
- 月份:取值为从 1 到 12 之间的任意整数;
- 星期:取值为从 0 到 7 之间的任意整数,0 或 7 代表星期日;
- 要执行的命令:要执行的命令或程序脚本等。
总共有 6 个字段,前 5 个字段用来指定任务重复执行的时间规律,第 6 个字段用于指定具体的任务内容。在 crontab 任务配置记录中,所设置的命令在“分钟+小时+日期+月份+星期”都满足的条件下才会执行。
时间周期的设置除了使用整数之外,还有一些特殊的符号表示方法:
- *:该范围内的任意时间;
- ,:间隔的多个不连续时间点;
- -:一个连续的时间范围;
- /:指定间隔的时间频率。
这里列举几个例子帮助大家理解这些特殊的符号表示方法:
- 0 23 * * 1-5:周一到周五每天 23:00。
- 30 2 * * 1, 3, 5:周一、周三、周五的 2 点 30 分。
- 0 8-18/2 * * *:每天 8 点到 18 点之间每隔 2 小时。
到这里大家应该对前 5 个时间字段非常熟悉了,那第 6 个字段呢?第 6 个字段既可以配置定时执行系统命令,也可以配置定时执行某个 Shell 脚本,我们通过几个案例演示一下。
【实例】每天凌晨 1:50 停止 sshd 服务,防止员工远程登录服务器,到早上 7:50 再启动 sshd 服务,让员工可以登录服务器进行工作。
[root@linux ~]# crontab -e 50 1 * * * systemctl stop sshd 50 7 * * * systemctl start sshd
【实例】每 3 分钟备份一次 /etc/passwd 文件,并将备份的文件备注上时间日期。
[root@linux ~]# mkdir /opt/PasswdBak #创建备份文件夹 [root@linux ~]# crontab -e #配置定时任务 [root@linux ~]# date #记一下时间 2024年 08月 22日 星期一 23:22:20 CST [root@linux ~]# crontab -l #查看刚才配置好的定时任务 */3 * * * * /usr/bin/cp -rf /etc/passwd /opt/PasswdBak/passwd-$(date +\%Y\%m\%d\%H\%M\%S) [root@linux ~]# date #等一小会 2024年 08月 22日 星期一 23:28:38 CST [root@linux ~]# ll /opt/PasswdBak/ #定时任务已自动执行了两次 总用量 8 -rw-r--r--. 1 root root 2793 8月 22 23:24 passwd-20240822232401 -rw-r--r--. 1 root root 2793 8月 22 23:27 passwd-20240822232701文件备份的时间周期建议一天一次或一周一次即可,案例中为了演示才把时间周期设置得这么短。
【实例】每 3 分钟执行一次 Shell 脚本。
[root@linux opt]# vim demo47.sh #写一个Shell 脚本,往 date.txt 中记录时间 #!/bin/bash echo "现在的时间是:`date +"%Y-%m-%d %H:%M:%S"`" >> /opt/date.txt [root@linux opt]# crontab -e #配置定时任务,使其每两分钟执行一次Shell 脚本 [root@linux opt]# date #记一下时间 2024年 08月 222日 星期一 23:55:45 CST [root@linux opt]# crontab -l #查看刚才配置好的定时任务 */2 * * * * * /bin/bash /opt/demo47.sh [root@linux opt]# date #等一小会 2024年 08月 23日 星期二 00:02:14 CST [root@linux opt]# cat /opt/date.txt #定时任务按定义配置正常运行中 现在的时间是:2024-08-222 23:56:01 现在的时间是:2024-08-22 23:58:01 现在的时间是:2024-08-23 00:00:01 现在的时间是:2024-08-23 00:02:01这个任务在实际工作中没有任何意义,但是可以很直接地验证定时任务是否可以正常执行,另外通过本案例还给大家演示了如何将定时任务和 Shell 脚本配合起来使用。
【实例】使用普通用户配置定时任务。
[root@linux ~]# su - lin #切换到普通用户 [lin@linux ~]$ crontab -e #配置定时任务 no crontab for lin - using an empty one [lin@linux ~]$ crontab -l ##查看刚才配置好的定时任务 */2 * * * * * /usr/bin/echo "1111111" >> /home/lin/date.txt [lin@linux ~]$ date #记一下时间 2022年 08月 23日 星期二 16:33:47 CST [lin@linux ~]$ date #等一小会 2022年 08月 23日 星期二 16:38:48 CST [lin@linux ~]$ cat date.txt #普通用户的定时任务正常运行中 1111111 1111111 1111111 [lin@linux ~]$ su - root #切换到 root 用户 密码: [root@linux ~]# crontab -l #默认查看自己配置的定时任务 */2 * * * * /bin/bash /opt/demo47.sh [root@linux ~]# crontab -l -u lin #查看指定用户配置的定时任务 */2 * * * * /usr/bin/echo "1111111" >> /home/lin/date.txt使用普通用户配置定时任务时,请注意权限问题。
Linux系统级别的定时任务
上文给大家演示了怎样通过 crontab 命令配置定时任务,每个用户都可以配置专属于自己的定时任务,这里再强调一下,每个用户在配置定时任务时还要考虑到自身权限的问题。既然有用户级别的定时任务,必然也会存在系统级别的定时任务。系统级别的定时任务需要用到配置文件 /etc/crontab。
不知道大家有没有注意到,在上文使用 crontab 命令配置定时任务时并没有指定用户,这是因为在通过 crontab -e 命令配置定时任务时,默认使用的身份是当前登录用户。而在通过修改 /etc/crontab 配置文件执行定时任务时,定时任务的执行者身份是可以手动指定的。这使得定时任务的执行变得更加灵活,修改起来也更加方便。
打开配置文件 /etc/crontab:
[root@linux ~]# 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,PATH 表示指定 PATH 环境变量,MAILTO 表示将任务的输出的结果发送到指定的邮箱。/etc/crontab 配置定时任务的语法格式如下:
50 3 2 1 * user-name run-command 分钟 小时 日期 月份 星期 用户名 要执行的命令相比 crontab 命令,/etc/crontab 多出了一个 user-name 字段,该字段用来定义用户名,表示在执行定时任务时所采用的用户身份。
我们将之前演示过的那些定时任务配置到 /etc/crontab 文件中,其实效果都是一样的,只不过多了表示用户身份的字段,示例如下:
[root@linux ~]# vim /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 */2 * * * * lin /usr/bin/echo "123456!!" >> /home/lin/date.txt */3 * * * * root /bin/bash /opt/demo47.sh */3 * * * * root /usr/bin/cp -rf /etc/passwd /opt/PasswdBak/passwd-$(date +\%Y\%m\%d\%H\%M\%S) [root@linux ~]# date #记一下时间 2024年 08月 23日 星期二 17:545 CST [root@linux ~]# date #等一小会 2024年 08月 23日 星期二 18:00:32 CST [root@linux ~]# ll /opt/PasswdBak/ -rw-r--r--. 1 root root 2560 08月 23 17:54 passwd-20240822175401 -rw-r--r--. 1 root root 2560 08月 23 17:57 passwd-20240822175701 -rw-r--r--. 1 root root 2560 08月 23 18:00 passwd-20240822180001 [root@linux ~]# cat /home/lin/date.txt #通过crontab命令和配置文件配置的两个定时任务同时在执行,互不影响 -----省略部分内容----- 1111111111 123456! 1111111111 123456! 1111111111 123456! 1111111111 123456! [root@linux ~]# cat /opt/date.txt #看结果,通过crontab命令和通过配置文件配置的两个定时任务同时在执行,互不影响 现在的时间是:2024-08-23 17:54:01 现在的时间是:2024-08-23 17:54:01 现在的时间是:2024-08-23 17:56:01 现在的时间是:2024-08-23 17:57:01 现在的时间是:2024-08-23 17:58:01 现在的时间是:2024-08-23 18:00:01 现在的时间是:2024-08-23 18:00:01 现在的时间是:2024-08-23 18:02:01 现在的时间是:2024-08-23 18:03:02 [root@linux ~]# crontab -l */2 * * * * /bin/bash /opt/demo47.sh只要将定时任务保存到 /etc/crontab 文件中,这个定时任务就可以执行了。当然,必须确定 crond 服务是正常运行的。
由示例可见,通过 crontab 命令和通过配置文件配置的定时任务之间是互不影响的,而且在 /etc/crontab 配置文件中配置的定时任务并不会通过 crontab 命令展示出来。