1.计划任务基本概述
crond
什么是crond,crond就是计划任务,类似于我们平时生活中的闹钟。定点执行。
计划任务主要是做一些周期性的任务,比如: 凌晨3点定时备份数据。或11点开启网站抢购接口,12点关闭抢占接口。计划任务主要分为以下两种使用情况:
1.系统级别的定时任务:临时文件清理、系统信息采集、日志文件切割
2.用户级别的定时任务:定时向互联网同步时间、定时备份系统配置文件、定时备份数据库的数据、重复性的工具(获取系统信息)
2.使用定时任务(服务)准备
yum安装
[root@dmxsp ~]# yum install -y cronie
启动并开机自启crond
[root@dmxsp ~]# systemctl start crond.service
[root@dmxsp ~]# systemctl enable crond.service
[root@dmxsp ~]# systemctl status crond.service
3.计划任务时间管理
Crontab配置文件记录了时间周期的含义 : 整体格式
[root@dmxsp ~]# 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) (分钟 0-59)
# | .------------- hour (0 - 23) (小时 0-23)
# | | .---------- day of month (1 - 31) (日期 1-31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ... (月份 1-12)
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat (周几 0-6 0或 7表示周日)
# | | | | |
# * * * * * user-name command to be executed
定时任务格式中的符号
*:表示任意的(分、时、日、月、周)时间都执行
-:表示一个时间范围段, 如5-7点
, (逗号):表示分隔时段, 如6,0,4表示周六、日、四
/1:表示每隔n单位时间, 如*/10 每10分钟
4.了解crontab的时间编写规范
00 02 * * * ls #每天的凌晨2点执行ls
00 02 1 * * ls #每个月的1号凌晨2点执行ls
00 02 14 2 * ls #每年的2月14日的凌晨2点执行ls
00 02 * * 7 ls #每周日的凌晨2点执行ls
00 02 * 6 5 ls #每年的6月的周五的凌晨2点执行ls
00 02 14 * 7 ls #每个月的14号或每周周日的凌晨02点执行ls #不推荐同时书写日期和周几#
00 02 14 2 7 ls #每年的2月14日或周日,凌晨2点执行ls
*/10 02 * * * ls #每天凌晨2点每隔10分钟执行 ls 2:00 2:10 2:20 2:30 2:40 2:50
* * * * * ls #每分钟执行一次 ls
00 00 14 2 * ls #每年的2月14日的半夜12点执行ls
*/5 * * * * ls #每五分钟 执行ls
00 02 * 1,5,8 * ls #每年1,5,8月的每天凌晨2点执行ls
00 02 1-8 * * ls #每月的1-8号的凌晨2点执行ls
00 02 * * * ls #每天的凌晨2点整执行
00 02 1 * * ls #每月的1日的凌晨2点整执行
00 02 14 2 * ls #每年的2月14日凌晨2点执行
00 02 * * 7 ls #每周天的凌晨2点整执行
00 02 * 6 5 ls #每年的6月周五凌晨2点执行
00 02 14 * 7 ls #每月14日或每周日的凌晨2点都执行
00 02 14 2 7 ls #每年的2月14日或每年2月的周天的凌晨2点执行
*/10 02 * * * ls #每天凌晨2点,每隔10分钟执行一次
* * * * * ls #每分钟都执行
00 00 14 2 * ls #每年2月14日的凌晨执行命令
*/5 * * * * ls #每隔5分钟执行一次
00 02 * 1,5,8 * ls #每年的1月5月8月凌晨2点执行
00 02 1-8 * * ls #每月1号到8号凌晨2点执行
使用crontab编写cron定时任务
参数 | 含义 |
crontab -e edit | 编辑定时任务 当前是root vi /var/spool/cron/root |
crontab -l list | 查看当前用户的定时任务 当前是root cat /var/spool/cron/root |
crontab -r remove | 清空/删除当前用户的所有定时任务 rm -f /var/spool/cron/root |
crontab -u user | 指定其他用户 |
5.计划任务编写实践
使用root用户每5分钟执行一次时间同步
[root@dmxsp ~]# yum install -y ntpdate
[root@dmxsp ~]# ntpdate time.windows.com
[root@dmxsp ~]# ntpdate ntp1.aliyun.com
[root@dmxsp ~]# crontab -e
no crontab for root - using an empty one
crontab: installing new crontab
[root@dmxsp ~]# crontab -l (需要绝对路径)
*/5 * * * * /usr/sbin/ntpdate ntp1.aliyun.com &>/dev/null
检查与测试
date
-s --set=STRING:根据字符串设置时间
-r --reference=FILE:显示文件的最后修改时间
-d --date=STRING:显示由字符串指定的时间, 而不是当前时间
-f --file=DATEFILE:类似于--date; 一次从DATEFILE处理一行
-R --rfc-822:根据 RFC-822 指定格式输出日期
-u --utc, --universal:显示或设置全球时间
FORMAT 参数
%%:输出字符%
%a:星期几的缩写 (Sun..Sat)
%A:星期的完整名称(Sunday..Saturday)。
%b:缩写的月份名称(例如,Jan)
%B:完整的月份名称(例如,January)
%c:本地日期和时间(例如,Thu Mar 3 23:05:25 2005)
%C:世纪,和%Y类似,但是省略后两位(例如,20)
%d:日 (01..31)
%D:日期,等价于%m/%d/%y
%e:一月中的一天,格式使用空格填充,等价于%_d
%F:完整的日期;等价于 %Y-%m-%d
%g ISO:标准计数周的年份的最后两位数字
%G ISO:标准计数周的年份,通常只对%V有用
%h:等价于 %b
%H:小时 (00..23)
%I:小时 (01..12)
%j:一年中的第几天 (001..366)
%k:小时,使用空格填充 ( 0..23); 等价于 %_H
%l:小时, 使用空格填充 ( 1..12); 等价于 %_I
%m:月份 (01..12)
%M:分钟 (00..59)
%n:新的一行,换行符
%N:纳秒 (000000000..999999999)
%p:用于表示当地的AM或PM,如果未知则为空白
%P:类似 %p, 但是是小写的
%r:本地的 12 小时制时间(例如 11:11:04 PM)
%R:24 小时制 的小时与分钟; 等价于 %H:%M
%s:自 1970-01-01 00:00:00 UTC 到现在的秒数
%S:秒 (00..60)
%t:插入水平制表符 tab
%T:时间; 等价于 %H:%M:%S
%u:一周中的一天 (1..7); 1 表示星期一
%U:一年中的第几周,周日作为一周的起始 (00..53)
%V:ISO 标准计数周,该方法将周一作为一周的起始 (01..53)
%w:一周中的一天(0..6),0代表星期天
%W:一年中的第几周,周一作为一周的起始(00..53)
%x:本地的日期格式(例如,12/31/99)
%X:本地的日期格式(例如,23:13:48)
%y:年份后两位数字 (00..99) %Y 年
%z:+hhmm 格式的数值化时区格式(例如,-0400)
%:z:+hh:mm 格式的数值化时区格式(例如,-04:00)
%::z:+hh:mm:ss格式的数值化时区格式(例如,-04:00:00)
%:::z:数值化时区格式,相比上一个格式增加':'以显示必要的精度(例如,-04,+05:30)
%Z:时区缩写 (如 EDT)
修改时间
[root@dmxsp ~]# date
Wed Jun 15 14:08:18 +08 2022
[root@dmxsp ~]# date -s "15:05:06"
Wed Jun 15 15:05:06 +08 2022
[root@dmxsp ~]# date
Wed Jun 15 15:05:08 +08 2022
看日志
[root@dmxsp ~]# tail -f /var/log/cron
查看定时任务
[root@dmxsp ~]# crontab -l
*/5 * * * * /usr/sbin/ntpdate ntp1.aliyun.com &>/dev/null (每五分钟执行一次)
查看时间
[root@dmxsp ~]# date
Wed Jun 15 14:40:56 +08 2022
案例:每天凌晨3点做一次备份? 打包备份/etc/到/tmp下
将备份命令写入一个脚本中
每天备份文件名要求格式:时间_hostname_ip_etc.tar.gz
在执行计划任务时,不要输出任务信息
存放备份内容的目录要求只保留三天的数据
在命令行先执行打包命令
[root@dmxsp ~]# tar zcf /tmp/$(date +%F)_$(hostname)_$(ip addr | awk ‘/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, “\\1”, “g”, $2)}’ )_etc.tar.gz /etc
[root@dmxsp ~]# ll /tmp/
total 10124
-rw-r–r– 1 root root 10366103 Jun 15 18:18 2022-06-15_dmxsp_10.0.0.22_etc.tar.gz
将命令写入至一个文件中
[root@dmxsp ~]# cat /root/dmxsp.sh
tar zcf /tmp/$(date +%F)_$(hostname)_$(ip addr | awk ‘/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, “\\1”, “g”, $2)}’ )_etc.tar.gz /etc
find /tmp/ -name ‘*.tar.gz’ -mtime +3 -exec rm -rf {} \;
配置定时任务
[root@dmxsp ~]# crontab -l
00 00 * * * sh /root/dmxsp.sh &>/dev/null
每天的下午3,5点,每隔半小时执行一次sync命令
[root@dmxsp ~]#crontab -l
*/30 15,17 * * * /usr/bin/sync &>/dev/null
crond如何拒绝某个用户使用
[root@dmxsp ~]# echo "lilei" >> /etc/cron.deny
[root@dmxsp ~]# crontab -e
You (lilei) are not allowed to use this program
(crontab)
See crontab(1) for more information
6.crond注意的事项
1.给定时任务注释, 表示说明 定时任务主要作用
2.将需要定期执行的任务写入Shell脚本中,避免直接使用命令无法执行的情况tar date %在定时任务中有特殊含义
3.定时任务的结尾一定要有&>/dev/null或者将结果追加重定向&>>/tmp/date.log文件
4.注意有些命令是无法成功执行的 echo “123” >>/tmp/test.log&>/dev/null
5.如果一定要是用命令,命令必须使用绝对路径
7.计划任务如何调试
1.crond调试
增加频率
1.调整任务每分钟执行的频率, 以便做后续的调试
2.调整系统时间
执行脚本输出到文件
1.如果使用cron运行脚本,请将脚本执行的结果写入指定日志文件, 观察日志内容是否正常
2.命令使用绝对路径, 防止无法找到命令导致定时任务执行产生故障
3.通过查看/var/log/cron日志,以便检查我们执行的结果,方便进行调试
2.crond编写思路
手动执行命令,然后保留执行成功的结果
编写脚本
1.统一路径:脚本需要统一路径/scripts
2.复制:脚本内容复制执行成功的命令(减少每个环节出错几率)
3.简单粗暴:脚本内容尽可能的优化, 使用一些变量或使用简单的判断语句
4.定向到空:脚本执行的输出信息可以重定向至其他位置保留或写入/dev/null
执行脚本
1.使用bash命令执行, 防止脚本没有增加执行权限(/usr/bin/bash)
2.执行脚本成功后,复制该执行的命令,以便写入cron
编写计划任务
1.加注释: 加上必要的注释信息, 人、时间、任务
2.改时间:设定计划任务执行的周期
3.去粘贴: 粘贴执行脚本的命令(不要手敲)
调试计划任务
1.增加任务频率测试
2.检查环境变量问题: 使用命令绝对路径
3.看日志:检查crond服务日志
8.不定时发送到钉钉
获取钉钉机器人Webhook
脚本
[root@master ~]$ cat rw/dsrw.sh
#!/bin/bash
#钉钉机器人的Webhook地址
webhook=’https://oapi.dingtalk.com/robot/send?access_token=627f4b88875a6c9ebb39c7ce6b4f49cd87587e7e27647424ca067dc9d4bcad71′
#随机消息数组
messages=(
“1.早上吃什么”
“2.晚上吃什么”
“3.中午吃什么”
)
#发送钉钉消息
send_message() {
local message=$1
curl -X POST -H ‘Content-Type: application/json’ -d ‘{“msgtype”: “text”, “text”: {“content”: “‘”$message”‘”}}’ $webhook
}
#记录开始时间
echo “开始时间: $(date)” >> /root/rw/dsrw.log
#随机选取第一条消息
first_index=$((RANDOM % ${#messages[@]}))
first_message=”${messages[$first_index]}”
#移除第一条消息,防止重复
unset messages[$first_index]
messages=(“${messages[@]}”) # 重新索引数组
#随机选取第二条消息
second_index=$((RANDOM % ${#messages[@]}))
second_message=”${messages[$second_index]}”
#发送第一条消息到钉钉
send_message “$first_message”
#等待一段时间后发送第二条消息
sleep $((RANDOM % 360)) # 随机等待时间(秒),范围是0到3599秒
#发送第二条消息到钉钉
send_message “$second_message”
#记录结束时间
echo “结束时间: $(date)” >> /root/rw/dsrw.log
解释
send_message() { local message=$1 curl -X POST -H 'Content-Type: application/json' -d '{"msgtype": "text", "text": {"content": "'"$message"'"}}' $webhook }
send_message() { … }: 定义一个名为send_message的函数。
local message=$1: 在函数内部声明一个局部变量message,并将其设置为函数的第一个参数(即传递给函数的消息内容)。
curl -X POST -H ‘Content-Type: application/json’ -d ‘{“msgtype”: “text”, “text”: {“content”: “‘”$message”‘”}}’ $webhook: 使用curl命令发送一个POST请求到钉钉机器人的Webhook URL。请求头设置为Content-Type: application/json,请求体是一个JSON对象,包含消息类型和内容。
echo "开始时间: $(date)" >> /root/rw/dsrw.log
echo “开始时间: $(date)” >> /root/rw/dsrw.log: 将当前时间(使用$(date)获取)记录到日志文件/root/rw/dsrw.log中,表示脚本的开始时间。
first_index=$((RANDOM % ${#messages[@]}))
first_index=$((RANDOM % ${#messages[@]})): 生成一个随机索引first_index,范围是从0到数组messages的长度减1。RANDOM是Bash内置的随机数生成器,%运算符用于取模,确保生成的索引在有效范围内。
first_message="${messages[$first_index]}"
first_message=”${messages[$first_index]}”: 从messages数组中提取索引为first_index的元素,并将其赋值给变量first_message。
unset messages[$first_index] messages=("${messages[@]}")
unset messages[$first_index]: 从messages数组中移除索引为first_index的元素。
messages=(“${messages[@]}”): 重新索引数组,以去除空洞(即移除元素后留下的空位)。
second_index=$((RANDOM % ${#messages[@]}))
second_index=$((RANDOM % ${#messages[@]})): 生成另一个随机索引second_index,范围是从0到更新后的数组messages的长度减1。
second_message="${messages[$second_index]}"
second_message=”${messages[$second_index]}”: 从更新后的messages数组中提取索引为second_index的元素,并将其赋值给变量second_message。
send_message "$first_message"
send_message “$first_message”: 调用send_message函数,将first_message作为参数传递,发送第一条消息到钉钉。
sleep $((RANDOM % 360)) # 随机等待时间(秒),范围是0到359秒
sleep $((RANDOM % 360)): 使脚本暂停一段时间,等待时间为0到359秒之间的随机秒数。RANDOM % 360生成一个0到359之间的随机数。
RANDOM是一个内置变量,它会生成一个介于 0 到 32767 之间的随机整数
send_message "$second_message"
send_message “$second_message”: 调用send_message函数,将second_message作为参数传递,发送第二条消息到钉钉。
echo "结束时间: $(date)" >> /root/rw/dsrw.log
echo “结束时间: $(date)” >> /root/rw/dsrw.log: 将当前时间(使用$(date)获取)记录到日志文件/root/rw/dsrw.log中,表示脚本的结束时间。
first_index=$((RANDOM % ${#messages[@]}))
first_message="${messages[$first_index]}"
first_index=$((RANDOM % ${#messages[@]}))
RANDOM: 这是Bash内置的一个特殊变量,每次引用时都会生成一个0到32767之间的伪随机整数。
${#messages[@]}: 这是一个数组长度表达式,用于获取数组messages的元素数量。messages是一个包含多条消息的数组。
%运算符: 这是取模运算符,用于计算除法后的余数。这里它用来确保生成的随机数在0到数组长度减1的范围内。
$((…)): 这是一个算术扩展语法,用于执行算术运算。在这里,它用于计算RANDOM % ${#messages[@]}的结果,并将结果赋值给first_index。
综合起来,这行代码的作用是从0到数组messages的长度减1之间生成一个随机索引,并将其存储在变量first_index中。
first_message=”${messages[$first_index]}”
${messages[$first_index]}: 这是一个数组元素访问表达式,用于从数组messages中获取索引为first_index的元素。first_index是上一行代码生成的随机索引。
first_message=…: 将获取到的消息内容赋值给变量first_message。
综合起来,这行代码的作用是从messages数组中提取索引为first_index的消息,并将其存储在变量first_message中。
unset messages[$first_index]
messages=("${messages[@]}")
unset messages[$first_index]
unset: 这是一个Bash内置命令,用于删除变量或数组元素。
messages[$first_index]: 这是指向数组messages中索引为first_index的元素。first_index是之前生成的随机索引。
综合起来,这行代码的作用是从数组messages中移除索引为first_index的元素。执行这行代码后,messages数组中将不再包含被移除的元素,但数组中的其他元素仍然保持原样,只是在被移除元素的位置上会留下一个空洞(即该位置的元素被删除了)。
messages=(“${messages[@]}”)
${messages[@]}: 这是一个数组扩展表达式,它会展开为数组messages的所有元素。
messages=…: 将展开后的数组元素重新赋值给messages数组。
综合起来,这行代码的作用是重新索引数组messages,以去除之前的空洞。具体来说,它创建了一个新的数组,并将旧数组的所有元素复制到新数组中,从而消除空洞,使数组连续
权限
chmod +x rw/dsrw.sh
定时任务
[root@master ~]$ crontab -l
0 18-19 * * * /root/rw/rw.sh &>>/root/rw/dsrw.log
0 19-20 * * * (sleep $((RANDOM % 360)); /root/rw/dsrw.sh) &>>/root/rw/dsrw.log
第一种执行方式
0 18-19 * * * /root/rw/rw.sh &>>/root/rw/dsrw.log
脚本
[root@master ~]$ cat rw/rw.sh
#!/bin/bash
sleep $((RANDOM % 360))
sh /root/rw/dsrw.sh
权限
chmod +x rw/rw.sh
第二种执行方式
0 19-20 * * * (sleep $((RANDOM % 360)); /root/rw/dsrw.sh) &>>/root/rw/dsrw.log
这里可能会执行不成功需要添加一个环境变量
vim /etc/profile
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
source /etc/profile
解释
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 这一行命令的作用是设置环境变量 PATH,它定义了系统在执行命令时查找可执行文件的目录列表。具体来说,这行命令将 PATH 环境变量设置为以下目录的组合:
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
详细解释
/usr/local/sbin: 这个目录通常用于存放系统管理员使用的本地安装的可执行文件。
/usr/local/bin: 这个目录通常用于存放本地安装的用户级可执行文件。
/usr/sbin: 这个目录通常用于存放系统管理员使用的系统级可执行文件。
/usr/bin: 这个目录通常用于存放系统级的用户可执行文件。
/sbin: 这个目录通常用于存放系统启动和维护所必需的系统级可执行文件。
/bin: 这个目录通常用于存放所有用户都可以使用的最基本命令。
执行结果
日志
tail -f rw/dsrw.log
开始时间: Sat Nov 30 18:03:02 CST 2024
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 88 100 27 100 61 111 252 --:--:-- --:--:-- --:--:-- 253
{"errcode":0,"errmsg":"ok"} % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 88 100 27 100 61 100 226 --:--:-- --:--:-- --:--:-- 226
{"errcode":0,"errmsg":"ok"}结束时间: Sat Nov 30 18:07:51 CST 2024
开始时间: Sat Nov 30 19:03:06 CST 2024
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 88 100 27 100 61 66 149 --:--:-- --:--:-- --:--:-- 149
{"errcode":0,"errmsg":"ok"} % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 88 100 27 100 61 70 159 --:--:-- --:--:-- --:--:-- 159
{"errcode":0,"errmsg":"ok"}结束时间: Sat Nov 30 19:06:07 CST 2024