crond: 是一款支持配置定时任务的软件,在几乎所有的Linux发行版中都是预安装的。
你只需要按照它规定的格式写好时间点+待执行的指令,就可以,非常简单 crond服务会定期(默认每分钟检查一次)检查系统中是否有要执行的任务工作,如果有,
便会根据其预先设定的定时任务规则自动执行该定时任务工作
日志文件:/var/log/cron
定时任务分类:
1、用户级定时任务
(1)通常由用户自己维护,系统管理员当然也可以维护
(2)定时任务的配置最终都会记录到文件中,用户级的定时任务文件位于/var/spool/cron/下,文件名是用户名。
(3)用户可以使用 crontab -e 命令来编辑自己的定时任务文件,使用 crontab -l 命令来列出自己的任务。( -u 指定用户)
2、系统级定时任务
(1)只有系统管理员可以编辑。
(2)系统级定时任务文件位于/etc目录下
存放命令
/etc/crontab:这是主crontab文件,包含了系统任务表,以及在预设时间执行的工作。
/etc/cron.d/:此目录存放任何想被cron守护进程执行的任务。
存放脚本:
/etc/cron.daily/:此目录下存放的任务脚本会被系统安排在每天凌晨执行。
/etc/cron.hourly/:此目录下存放的任务脚本会被系统安排每小时执行一次。
/etc/cron.monthly/:此目录下存放的任务脚本会被系统安排在每月的某一天执行。
/etc/cron.weekly/:此目录下的任务脚本会被系统安排在每周的某一天执行。
系统级定时任务主要用于如:临时文件清理例/tmp和/var/tmp等、系统信息采集、日志文件切割等场景
用户级定时任务主要用于如:定时向互联网同步时间、定时备份系统配置文件、定时备份数据库的数据等场景
1、编辑文件/etc/crontab
分----时----日----月----周 * * * * * 周(0 / 7 表示今天)
# * * * * * user-name command to be executed
#* * * * * user echo "$(date) 执行拉" >> /tmp/system_run.log
2、将脚本放于目录中 脚本需要chmod+x(执行权限)
run-parts # 执行改目录下的全部脚本
#当前在哪个用户计划任务就创建到哪个用户
[root@localhost ~]# crontab -e # 创建计划任务
* * * * * echo `date` >> /tmp/a.log
[root@localhost ~]# crontab -l # 查看计划任务
* * * * * echo `date` >> /tmp/a.log
[root@localhost ~]# ls /var/spool/cron/
root
[root@localhost ~]# cat /var/spool/cron/root # 都是写在这里呢
* * * * * echo `date` >> /tmp/a.log
[root@localhost ~]# tail /var/log/cron # 查看日志
# /etc/cron.deny 是定时任务的黑名单,使用root将需要拒绝的用户加入/etc/cron.deny
[root@localhost ~]# echo "egon" >> /etc/cron.deny
# 登陆该普通用户,无法编写定时任务
cron 守护进程每分钟都会自动检查 /etc/crontab 文件、etc/cron.d/ 等目录中的改变。如果发现了改变,它们就会被载入内存。所以你如果修改了计划人文导致其crontab文件改变后,并不需要重启守护进程。
crontab的用户手册中推荐每一个命令使用绝对路径,例如调用rm命令时写作:/bin/rm,这是为了防止由于每一个用户的PATH环境变量不同而导致命令无法找到的错误。
编写定时任务时,先在命令行上面执行一次,查看是否可以执行成功。
把定时任务执行的结果定向到空&>/dev/null,如果不定向到空的话,邮件服务postfix开启时(centos7.9),系统会一直发送邮件信息日积月累会白白耗费磁盘空间。# systemctl stop postfix.service 也可以直接关闭服务
* * * * * #每分钟执行一次
*/10 02 * * * #每天凌晨2点,每隔10分钟执行一次
00 02 14 2 * #每年的2月14日凌晨2点执行一次
00 02 * 6 5 #每年的6月份整个月中、每到周五凌晨2点就会执行一次
"日期穿刺"问题:当日期字段和星期字段都被特定的值所指定时,那么满足其中任意一个字段的条件,任务就会被执行,两者都有两个时间都会被执行
00 02 14 * 7 #每月14日或每周日的凌晨2点都执行
00 02 14 2 7 #每年的2月14日或每年2月的周天的凌晨2点执行
00 02 1-8 * * #每月1号到8号凌晨2点都会执行一次
45 4 1,10,22 * * #每月1、10、22日的4:45执行一次
45 4 1-10 * * #每月1到10日的4:45执行一次
3,15 8-11 */2 * * #每隔两天的上午8点到11点的第3和第15分钟执行
0 23-7/2 * * * #晚上11点到早上7点之间,每隔两小时执行
[root@localhost ~]# crontab -l
* * * * * /usr/bin/date +\%F_\%T >> /root/time.txt #有些特殊符号会被误解,需要进行转义 \ , 或者直接写成脚本文件
echo $PATH ### 查询当前环境变量
[root@localhost ~]# cat /root/bak.sh
#!bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin ### 防止下述命令出问题// 每条路径使用绝对路径
mkdir /backup
cd /
tar -czf backup/$(hostname)_$(date +\%F_\%T)_etc.tar.gz /etc
find backup -type f -name "*.tar.gz" -mtime +3 |xargs rm -rf
[root@localhost ~]# crontab -l
00 03 * * * /bin/bash /root/bak.sh &>/dev/null
第一,脚本代码有问题,解决:先手动调试跑通
第二,执行环境问题:手动执行成功而crontab不能执行的时候,很可能就是执行环境的问题,例如相关路径的设置问题,可以在代码最前面执行 source /home/user/.bash_profile
第三,系统时间不正确。这种问题最好理解,也是比较常见和隐蔽的问题,解决方案:date -s ********
第四,就是我们的脚本是否有可执行权限。必须保证执行脚本的用户有执行改文件的权限。
第五,crontab 守护进程死掉了。这种情况是极少发生的,但也不排除,当我们实在是找不到其他原因的时候可以用。解决方案:重启该进程。
第六,crontab不执行的问题困扰了好长时间,脚本写的都正确,但是就是不执行,最终解决方法如下:
crontab -u root /var/spool/cron/root
这样root用户的crontab就生效了
[root@localhost ~]# systemctl restart crond
重启下服务就好了
第七,crond没有启动
第八,脚本编码问题,脚本在window下编写,传到linux下后报“锘?!/bin/bash”,用vi编辑器新建新shell脚本,输入内容后保存。
第九:特殊符号无法识别,需要添加转义(见示例)
1.先自己手动把命令一条一条执行一下,确保你的命令符合你的预期
2.然后再把你调试后的一条条命令扔到文件里,这个文件我们称之为一个脚本脚本的存放路径最好统一为 /scripts
3.执行脚本
使用bash命令执行,防止脚本没有增加执行权限(/usr/bin/bash /bin/bash),确保可以正常执行且结果符合预期
4.编写定时任务
可以加上必要的注释信息,人、时间、任务
# 每分钟执行一条xxx命令
* * * * * /bin/bash /scrips/run.sh
设定定时任务执行的周期
粘贴步骤3中你执行脚本的命令(不要手敲)
5.调试定时任务
可以先用*让脚本在1分钟内存触发,确保真的可以触发
如果发现没有触发,则要检查环境变量问题(最好在脚本中重新定义环境变量PATH)
检查日志/var/log/cron
监控脚本
监控---》(cpu(利用率、系统负载)、内存、磁盘、网络、进程)+计划任务
可压缩资源------》cpu (可以取一段时间内的平均值判断)
不可压缩资源---------》内存 硬盘 (只能取瞬时值进行判断)
监控cpu的使用率脚本
获取cpu的运行状态,从多个状态从取出想要的那一个(cpu的使用率)
判断 cpu的使用率 超过 100
发送告警
否则
啥事也不用做
# 监控cpu使用率
cpu_free=$(vmstat 1 2|awk 'NR==4{print $(NF-2)}')
if [ $cpu_free -eq 0 ];then
echo "主机:`hostname` cpu剩余率 为0" >> /tmp/warn.log
fi
#vmstat 1 2 状态每一秒记录一次共执行两次
### 取瞬时数据容易造成许多无效报警------优化:需要取一段时间内的多次数据的平均值进行判断 // 或者取完一次数据后sleep一段时间再次取数据检测是否需要报警,如果依然超过阈值就进行报警,如果恢复正常便不需要
监控系统负载
load_average=$(uptime |awk '{print $(NF-2)}' |cut -d, -f1|cut -d. -f1) #不支持浮点数必须cut为整数
load_average_limit=$(($(grep 'processor' /proc/cpuinfo |wc -l) * 2)) #设置两倍阈值
if [ $load_average -ge $load_average_limit ];then
echo "主机:`hostname` 系统负载达到阈值$load_average_limit" >> /tmp/warn.log
fi
#uptime---只取负载那一行的信息
# 监控内存:内存使用超过90%则报警(或则剩余<10%) (阈值为实际情况自定义)
MEM_LIMIT=80
available=`free |awk '/Mem/{print $NF}'`
total=`free |awk '/Mem/{print $2}'`
mem_percent=`echo "scale=2;$available / $total" |bc|cut -d. -f2`
echo $mem_percent
if [ $mem_percent -lt $MEM_LIMIT ];then
echo "$hostname memory 剩余量不足 10%" >> /tmp/warn.log
fi
# 监控磁盘:根分区使用超过80%则报警
DISK_LIMIT=85
disk_use=$(df |awk '/sda3/{print $(NF-1)}' |cut -d'%' -f1)
if [ $disk_use -gt $DISK_LIMIT ];then
echo "$hostname 磁盘使用率超过了85%" >> /tmp/warn.log
fi
邮件监控
(邮箱需要开启POP3/SMTP)
创建/scripts/mail.py
#!/usr/bin/python
#coding:utf-8
import smtplib
import sys
from email.mime.text import MIMEText
from email.header import Header
# 1、需要定制的部分
# 发送方账号
sender = '[email protected]'
# 发送方授权密码
password = 'xxxx'
# 收件方邮箱
receiver = '[email protected]'
# 邮件标题
subject = sys.argv[1] # =========> 针对命令“/usr/bin/mail.py 邮件标题 邮件内容”,sys.argv[1]接收到邮件标题
# 邮件内容
mail_msg = sys.argv[2] # =========> 针对命令“/usr/bin/mail.py 邮件标题 邮件内容”,sys.argv[1]接收到邮件内容
# 三个参数:第一个为文本内容,第二个 plain 设置文本格式,html 设置文本格式为html格式 第三个 utf-8 设置编码
# 2、以下是固定代码
# 发送邮件服务器地址
smtp_server = 'smtp.163.com'
message = MIMEText(mail_msg, 'plain', 'utf-8') # 发送内容 (文本内容,发送格式,编码格式)
# 发送地址
message['From'] = sender
# 接受地址
message['To'] = receiver
# 邮件标题
message['Subject'] = Header(subject,'utf-8')
try:
print("发送邮件")
# 创建SMTP对象
smtp = smtplib.SMTP_SSL(smtp_server)
smtp.set_debuglevel(1)
# 登录邮箱账号
smtp.login(sender, password)
# 发送账号信息
smtp.sendmail(sender, receiver, message.as_string())
print('success:发送成功')
except smtplib.SMTPException:
print('error:邮件发送失败')
finally:
# 关闭
smtp.quit()
授权,链接PATH路径下
chmod +x /scripts/mail.py
ln -s /scripts/mail.py /usr/bin/mail
mail "测试邮件" "哈哈哈哈哈哈" # 注意内容部分要用引号包裹,因为可能有空格
建立监控脚本
#!/bin/bash
cpu_limit=0 #cpu使用超过90%则报警,此处我们为了得到报警邮件的实验效果,直接设置成0
mem_limit=0 #内存使用超过90%则报警,同上
disk='/dev/sda1' #需要监控的磁盘名
disk_inode_limit=0 #磁盘inode使用超过90%则报警,同上
disk_space_limit=0 #磁盘空间使用超过90%则报警,同上
function monitor_cpu(){
cpu_free=`vmstat 1 5 |awk 'NR>=3{x = x + $15} END {print x/5}' |awk -F. '{print $1}'`
cpu_use=$((100-cpu_free))
if [ $cpu_use -gt $cpu_limit ]
then
msg="TIME:$(date +%F_%T)
HOSTNAME:$(hostname)
IPADDR:$(ifconfig |awk 'NR==2{print $2}')
MSG:CPU usage exceeds the limit,current value is ${cpu_use}%"
echo $msg
/usr/bin/mail "cpu告警信息" "$msg"
fi
}
function monitor_mem(){
mem_total=`free |awk 'NR==2{print $2}'`
mem_use=`free |awk 'NR==2{print $3}'`
mem_per=`echo "scale=2;$mem_use/$mem_total" |bc -l|cut -d. -f2`
if [ $mem_per -gt $mem_limit ]
then
msg="TIME:$(date +%F_%T)
HOSTNAME:$(hostname)
IPADDR:$(ifconfig |awk 'NR==2{print $2}')
MSG:Memory usage exceeds the limit,current value is ${mem_per}%"
echo $msg
/usr/bin/mail "内存告警信息" "$msg"
fi
}
function monitor_disk_inode(){
inode_use=`df -i $disk |awk 'NR==2{print $5}' |cut -d% -f1`
if [ $inode_use -gt $disk_inode_limit ]
then
msg="TIME:$(date +%F_%T)
HOSTNAME:$(hostname)
IPADDR:$(ifconfig |awk 'NR==2{print $2}')
MSG:Disk inode usage exceeds the limit,current value is ${inode_use}%"
echo $msg
/usr/bin/mail "硬盘innode信息" "$msg"
fi
}
function monitor_disk_space(){
space_use=`df $disk |awk 'NR==2{print $5}'|cut -d% -f1`
if [ $space_use -gt $disk_space_limit ]
then
msg="TIME:$(date +%F_%T)
HOSTNAME:$(hostname)
IPADDR:$(ifconfig |awk 'NR==2{print $2}')
MSG:Disk space usage exceeds the limit,current value is ${space_use}%"
echo $msg
/usr/bin/mail "硬盘空间信息" "$msg"
fi
}
monitor_cpu &>> /tmp/monitor.log
monitor_mem &>> /tmp/monitor.log
monitor_disk_inode &>> /tmp/monitor.log
monitor_disk_space &>> /tmp/monitor.log
授权测试
chmod +x /scripts/servermonitor.sh
/scripts/servermonitor.sh # 本地跑一下测试一下
1.定时任务规则之前加注释
2.使用脚本执行定时任务(只有一条简单命令的可以直接使用命令执行)
3.运行脚本一定要用绝对路径执行,并且最好统一脚本位置,
4.定时任务中date命令的百分号需转义才能使用。
5.命令或脚本结果(正确及错误)定向到空(&>/dev/null)或追加到文件中 &>>/tmp/run.log
6.避免不必要的程序及命令输出,如打包命令,tar -v的显示过程的选项。
7.打包压缩使用相对路径(切到目标目录的上一级打包目标,否则可能会带着一层目录)
8.定时任务脚本中的程序文件 ,尽量用绝对路径---iptables命令在计划任务中必须写绝对路径/sbin/iptables
9.系统与命令位置有关的环境变量问题,建议脚本中重新定义环境变量PATH