1. 定时任务Crond介绍
1.1 Crond是什么?
Crond是Linux系统中用来定期执行命令或指定程序任务的一种服务或软件。
一般情况下,CentOS5/6 Linux操作系统之后,默认便会启动Crond任务调度服务。
在我们前面的系统安装及开机启动优化的设置中,我们也设置保留了Crond开机自启动。
Crond服务会定期(默认每分钟检查一次)检查系统中是否有要执行的任务工作。
如果有,便会根据其预先设定的定时任务规则自动执行该定时任务工作。
这个Crond定时任务服务就相当于我们平时早起使用的闹钟一样。
特殊需求:
Crond服务搞不定了,一般工作中写脚本守护程序执行。
例子:
每隔1s向屏幕输出一条"I am oldboy teacher."
[root@oldboy exercise]# cat cron.sh while true do echo "I am oldboy teacher." sleep 1 done
- 程序文件:程序代码组成,但是没有在计算机内执行。当前没有执行。
- 进程:所谓进程就是计算机中正在执行的程序
- 守护进程或守护程序:就是一直运行的程序。
操作命令:
批量关闭开机运行级别为3的开启的所有服务,然后再批量开启指定的需要开启的服务:crond,syslog,sshd,network,sysstat。
LANG=en for oldboy in `chkconfig --list|grep '3:on'|awk '{print $1}'`;do chkconfig --level 3 $oldboy off;done for oldboy in crond network syslog sshd sysstat;do chkconfig --level 3 $oldboy on;done chkconfig --list|grep 3:on
1.2 为什么要使用crond定时任务
linux系统的定时任务crond,相当于我们平时生活中的闹钟的功能。可以满足周期性执行任务的需求。
1.3 不同系统的定时任务和种类
1.3.1 windows 7 系统的定时任务
开始→所有程序→附件→系统工具→选择任务计划程序
1.3.2 linux系统的定时任务
linux系统中定时任务调度的工作可以分为以下两个情况:
- Linux系统自身定期执行的任务工作:系统周期性执行的任务工作,如:轮询系统日志,备份系统数据,清理系统缓存等。 这些任务无需我们人为干预。
例如:系统的日志/var/log下的messages*
[root@oldboy log]# ll messages* -rw------- 1 root root 379276 Sep 10 20:14 messages -rw-------. 1 root root 587982 Sep 1 03:47 messages-20190901 -rw------- 1 root root 5778 Oct 1 2019 messages-20190904 -rw------- 1 root root 72300 Sep 9 20:11 messages-20190909 -rw-------. 1 root root 457761 Oct 1 2019 messages-20191001
- 用户执行的任务工作:某个用户或系统管理员定期要做的任务工作,例如每隔5分钟和互联网上时间服务器进行时间同步,每天晚上0点备份站点数据及数据库数据,一般这些工作需要由每个用户自行设置才行。
例如:服务器时间同步:每五分钟同步一次系统时间
[root@CentOS6 log]# crontab -l #time sync by lee at 2014-1-14 */5 * * * * /usr/sbin/ntpdate time.windows.com >/dev/null 2>&1
补充:
# 查看/etc/目录下包含 cron的文件或目录 [root@oldboy log]# ll /etc/|grep cron -rw-------. 1 root root 541 Mar 30 2015 anacrontab drwxr-xr-x. 2 root root 4096 Aug 30 07:21 cron.d drwxr-xr-x. 2 root root 4096 Aug 30 07:21 cron.daily -rw-------. 1 root root 0 Mar 30 2015 cron.deny drwxr-xr-x. 2 root root 4096 Aug 30 07:20 cron.hourly drwxr-xr-x. 2 root root 4096 Aug 30 07:21 cron.monthly -rw-r--r--. 1 root root 457 Sep 27 2011 crontab drwxr-xr-x. 2 root root 4096 Sep 27 2011 cron.weekly
[root@oldboy logrotate.d]# cd /etc/logrotate.d/ [root@oldboy logrotate.d]# cat syslog /var/log/cron /var/log/maillog /var/log/messages /var/log/secure /var/log/spooler { sharedscripts postrotate /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true endscript }
2. 定时任务crond使用说明
crond是一个服务,crontab是一个命令
crond服务通过crontab命令可以很容易的实现周期性的日志分析或数据备份等运维场景工作
2.1 指令说明
[root@oldboy logrotate.d]# crontab --help crontab: invalid option -- '-' crontab: usage error: unrecognized option usage: crontab [-u user] file crontab [-u user] [ -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) -s (selinux context)
crontab选项:
- -e (edit user's crontab) 编辑crontab文件内容
- crontab -e 相当于 vi /var/spool/cron/root
- -l (list user's crontab) 查看crontab文件内容。
- crontab -l 相当于 cat /var/spool/cron/root
- -r (delete user's crontab) 删除crontab文件内容,remove,极少用
- -i (prompt before deleting user's crontab) 删除crontab文件内容,删除前会提示确认,用的很少
- -s (selinux context)
- -u user 指定使用的用户执行任务
- crontab -u oldboy -l
特别强调:
- -i, -r参数在生产中极少用
- -e参数,没什么需求必须要用-e进去编辑
- cron {-l|-e} 实际上就是在操作/var/spool/cron/当前用户 这样的文件。
- crontab -e 会检查语法;vi /var/spool/cron/root 不会检查语法
- visudo 会检查语法;vi /etc/sudoers 不会检查语法
通过crontab,我们可以在固定的间隔时间执行指定的系统指令或script脚本。
时间间隔的单位是分钟,小时,日,月,周及以上的任意组合(注意:日和周不要组合)
使用者权限及定时任务文件
文件 | 说明 |
---|---|
/etc/cron.deny | 该文件中所列用户不允许使用crontab命令 |
/etc/cron.allow | 该文件中所列用户允许使用crontab命令,优先于/etc/cron.deny |
/etc/spool/cron | 所有用户crontab配置文件默认都存放在此目录,文件名以用户名命名 |
指令的使用格式
默认情况下,当用户建立定时任务规则后,该规则记录对应的配置文件会存放于/var/spool/cron中,其中crontab配置文件对应的文件名与登录的用户名一致。
如:
root用户的定时任务配置文件为 /var/spool/cron/root
crontab用户的定时任务一般分为6段(空格分隔,系统的定时任务则/etc/crontab分为7段),其中前5段为时间设定段,第6段为所要执行的命令或脚本任务段。
crontab基本格式
* * * * * cmd
提示:
- cmd为要执行的命令或脚本,例如:/bin/sh /server/scripts/lee.sh
- 每个段时间必须要有空格
例如:
[root@oldboy cron]# cat /etc/crontab SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ # 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
crontab语法格式中时间段的含义
段 | 含义 | 取值范围 |
---|---|---|
第1段 | 分钟 | 0-59 |
第2段 | 小时 | 0-23 |
第3段 | 日期 | 1-31 |
第4段 | 月份 | 1-12 |
第5段 | 星期 | 0-7(0和7都代表星期日) |
提示:时间记忆口诀:分时日月周。
crontab语法格式中特殊符号的含义
- * 表示任意时间都,就是"每"的意思
- 如00 01 * * * cmd表示每月每周每日的凌晨1点执行cmd任务。
- - 减号,表示分隔符,表示一个时间范围段,
- 如17-19点,每小时的00分执行任务。
- 00 17-19 * * * cmd。就是17,18,19点整点分别执行的意思。
- , 逗号,表示分隔时间段的意思。
- 30 17,18,19 * * * cmd 表示每天17,18,19点的30分执行cmd。
- 也可以和“-”结合使用,如: 30 3-5,17-19 * cmd。
- /n n代表数字,即“每隔n单位时间”
- 例如:每10分钟执行一次任务可以写 */10 * * * * cmd,其中 */10,*的范围是0-59,也可以写成0-59/10。
crontab编辑的定时任务依赖的服务
没有crond服务,crontab无法运行。
# 查看crond服务状态 [root@oldboy /]# chkconfig --list crond crond 0:off 1:off 2:on 3:on 4:on 5:on 6:off # 重启crond服务 [root@oldboy /]# /etc/init.d/crond restart Stopping crond: [ OK ] Starting crond: [ OK ] # 查看crond 进程 [root@oldboy /]# ps -ef|grep crond root 2343 1 0 21:42 ? 00:00:00 crond root 2346 1290 0 21:42 pts/0 00:00:00 grep crond [root@oldboy /]# ps -ef|grep crond|grep -v grep root 2343 1 0 21:42 ? 00:00:00 crond
下面是几个定时任务的描述例子:
题目1: 30 3,12 * * * /bin/sh /scripts/oldboy.sh
解析意思:每天凌晨3点半和中午12点半,执行/scripts/oldboy.sh脚本。
题目2: 30 */6 * * * /bin/sh /scripts/oldboy.sh
解析: 每隔6个小时的半点时刻执行/scripts/oldboy.sh脚本任务
题目3: 30 8-18/2 * * * /bin/sh /scripts/oldboy.sh
解析:8点到18点,每隔2个小时,相当于每天的8,10,12,14,16,18的半点时刻执行/scripts/oldboys.sh脚本任务
题目4:30 21 * * * /application/apache/bin/apachectl graceful
解析:每天晚上21点半,重启apache
题目5:45 4 1,10,22 * * /application/apache/bin/apachectl graceful
解析:每月的1号,10号,22号的4点45分,重启apache
题目6:10 1 * * 6,0 /application/apache/bin/apachectl graceful
解析:每周的星期六和星期日的1点10分,重启apache
题目7:0,30 18-23 * * * /application/apache/bin/apachectl graceful
解析:每天的18到23点的整点和半点(即18-23点,每隔30分钟),重启apache
题目8:00 */1 * * * /application/apache/bin/apachectl graceful
解析:每天每隔1个小时,重启apache
题目9:* 23,00-07/1 * * * /application/apache/bin/apachectl graceful
解析:并不是“每天的23点到次日的凌晨7点,每隔一个小时,重启apache”,表示每分都执行任务,即“晚上23点和早上0-7点之间,每隔一小时的每份都重启apache,很可怕。”
这题的写法就不规范,要想表示23点到次日凌晨7点每隔一小时执行重启apache,则"0 23,00-07/1 * * * /application/apache/bin/apachectl graceful"
题目10:00 11 * 4 1-3 /application/apache/bin/apachectl graceful
解析:每年的4月的每周1到周三的上午11点整重启apache。
注意:周和日尽量不要同时用,否则可能达不到想要的效果。
crond服务的启动和停止:
/sbin/service crond start 启动服务 /sbin/service crond stop 关闭 /sbin/service crond restart 重启 /sbin/service crond reload 重新载入配置 /sbin/service crond status 查看服务状态
3. 书写crond定时任务7个基本要领
样例:
[root@angelT ~]# crontab -l #backup www to /backup 00 00 * * * /bin/sh /server/scripts/www_bak.sh >/dev/null 2>&1
- 为定时任务规则加必要的注释
- 定时任务命令或程序最好写到脚本里执行
- 定时任务执行的脚本要规范路径,如:/server/scripts
- 执行shell脚本任务时,前加/bin/sh 命名,否则有可能因为忘了脚本设定执行权限,从而无法完成任务
- 定时任务结果加 >/dev/null 2>&1
- 在指定用户下执行相关的定时任务
- 要特别注意不同用户的环境变量问题,如果是调用了系统环境变量/etc/profile,最好在程序脚本中将用到的环境变量重新export下。
- 生产任务程序不要随意打印输出信息
- 在调试好脚本程序后,应尽量把DEBUG及命令输出的内容信息屏蔽掉,如果确实需要输出日志,可定向到日志文件里,避免产生系统垃圾。
[root@oldboy /]# ll /dev/null crw-rw-rw- 1 root root 1, 3 Sep 10 2019 /dev/null
有关/dev/null的说明:
- /dev/null为特殊的字符设备文件,表示黑洞设备或空设备
2>&1:
- 2>&1 就是把标准错误重定向到标准输出(>&)
- >/dev/null 2>&1 等价于 1>/dev/null 2>/dev/null
>/dev/null 2>&1的作用:
如果定时任务规范结尾不加 >/dev/null 2>&1,很容易导致硬盘inode空间被占满,从而系统服务不正常(var/spool/clientmqueue邮件临时队列目录,邮件服务关闭状态下,队列中的任务会一直排列,小文件大量消耗inode。如果是centos 6.4系统,默认不装sendmail服务,所以不会有这个目录。)
配置定时任务规范操作过程
-
首先要在命令行操作成功,然后复制成功的命令到脚本里,在各个细小环境减少出错的机会。
-
然后测试小本,测试成功后,复制脚本的规范路径到定时任务配置里,不要手敲。
-
先在测试环境下测试,然后正式环境规范部署。
4. 生产场景如何调试crond定时任务
规范的公司开发和运维人员操作流程:
个人的开发配置环境-->办公室的测试环境-->idc机房的测试环境-->idc机房的正式环境。
4.1 增加执行频率调试任务
在调试时,把任务执行频率调快一点,看能不能正常执行,如果正常,那就没问题了,再改成需要的任务的执行时间。
注意:
有些任务时不允许频繁执行的,例如:定时往数据库里插入数据,这样的任务要在测试机上测试好,然后正式线上出问题的机会就少了。
4.2 调整系统时间调试任务
用正确的执行任务的时间,设置完成后,可以修改下系统当前时间,改成任务执行时间的前几分钟来测试(或者重启定时任务服务)
4.3 通过日志输出调试定时任务
在脚本中加入日志输出,然后把输出打到指定的日志中,然后观察日志内容的结果,看是否正确执行。
4.4 注意一些任务命令带来的问题
注意:
- 不能做双重重定向,不能有两个标准输出:
* * * * * echo “==”>>/tmp/lee.log >/dev/null 2>&1 这里隐藏的无法正确执行的任务配置,原因是前面多了>>,或者去掉结尾的 >/dev/null 2>&1。 - %要转义(脚本中无需转义) * * * * * tar zvf /tmp/service-oldboy-$(date +\%F-\%H).tar.gz /etc/services
4.5 注意环境变量导致的定时任务障碍
例如:在调试java程序任务的时候,注意环境变量,把环境变量的定义加到脚本里。
4.6 通过定时任务日志调试定时任务
[root@oldboy ~]# tail -f /var/log/cron Sep 12 23:16:01 oldboy CROND[1780]: (root) CMD (echo oldboy >>/server/log/oldboy.log) Sep 12 23:17:01 oldboy CROND[1782]: (root) CMD (echo oldboy >>/server/log/oldboy.log) Sep 12 23:18:01 oldboy CROND[1784]: (root) CMD (echo oldboy >>/server/log/oldboy.log) Sep 12 23:19:01 oldboy CROND[1786]: (root) CMD (echo oldboy >>/server/log/oldboy.log) Sep 12 23:20:01 oldboy CROND[1791]: (root) CMD (echo oldboy >>/server/log/oldboy.log) Sep 12 23:20:01 oldboy CROND[1792]: (root) CMD (/usr/sbin/ntpdate time.windows.com >/dev/null 2>&1) Sep 12 23:20:01 oldboy CROND[1793]: (root) CMD (/usr/lib64/sa/sa1 1 1) Sep 12 23:21:01 oldboy CROND[1798]: (root) CMD (echo oldboy >>/server/log/oldboy.log) Sep 12 23:22:01 oldboy CROND[1800]: (root) CMD (echo oldboy >>/server/log/oldboy.log) Sep 12 23:23:01 oldboy CROND[1875]: (root) CMD (echo oldboy >>/server/log/oldboy.log)
5. crontab定时任务生产应用问题的10条注意事项:
- 系统环境变量导致定时任务执行问题
- crontab执行shell时只能识别为数不多的系统环境变量, 普通环境变量一般是无法识别的,如果在编写的脚本中需要使用变量,最好使用export重新声明下该变量, 以确保脚本正确执行。
- 定时任务里面的命令要用绝对路径
- 脚本权限问题,加/bin/sh
- 时间变量问题用反斜线\%转义,最好用脚本,脚本不需要转义
- %在crontab任务中被认为是newline,所以需要用转义符号
- >/dev/null 2>&1
- sendmail或postfix邮件服务关闭时,邮件队列堆积,小文件大量消耗inode造成磁盘空间不足。
- 加上这个可以避免inode不足的问题的发生
- 定时任务规则之前加注释
- 使用脚本程序替代命令行定时任务
- 避免不必要的程序及命令输出
- 切到目标目录的上一级打包目标
- 定时任务脚本中的程序命令尽量用全路径(和环境变量的识别有关)
6. crontab生产问题案例及解决问题
面试题:在系统维护的时候,创建文件提示"No space left on device",请问是什么故障?
解答:
磁盘空间block满了或inode被占满了。
故障描述及说明:
某年某月甘日某时,某人在工作中设置crontab定时任务规则保存时,提示” No space left on device”,此时用df -h检查磁盘,发现还有剩余空间,用df -I 检查则显示/var目录己占用100%的inode数量,看来是inode数量耗尽,导致系统无法在/var目录下创建文件,因为定时任务的配置在/var/spool/cron下,ext3文件系统中,每个文件需要占一个inode。
No space left on device 故障解决办法:
最后经过检查发现在/var/spool/clientmqueue/下有超多的文件,执行ls /var/spool/clientmqueue命令查看,很长时间没能显示出结果,执行cd /var/spool/clientmqueue;rm –f *会自动跳出来,也是无法删除,最后只能通过xargs命令来配合解决,清理实际命令为: cd /var/spool/clientmqueue&&ls|xargs rm –f
在清理时,如果数量特别多的时候,执行 ls|xargs rm –f 命令也会长时间无反应。
那是命令在处理中,当然我们也可以使用更快的删除方法,如直接使用
cd /var/spool&&rm –rf clientmqueue # 删除上级目录
然后执行
mkdir clientmqueue&&chmod 770 clientmqueue&&chown smmsp.smmsp -R /var/spool/clientmqueue
修改回/var/spool/clientmqueue目录在系统中的原来默认权限
[root@localhost scripts]# ls -ld /var/spool/clientmqueue/
drwxrwx---. 2 smmsp smmsp 4096 Nov 26 15:41 /var/spool/clientmqueue/
故障原因分析:
当系统中crond定时任务执行程序有输出内容时,输出内容会以邮件形式发给crond的用户(默认是root),而sendmail等mail服务没有启动时,这些输出内容以为支在邮件队列临时目录,产生这些碎文件,导致消耗inode数量,一旦inode数量耗尽,就会导致系统无法写入文件,而报上述错误:No space left on device.
亡羊补牢解决方法:
1) 尽量将crontab里面的命令或脚本中的命令结尾加上>/dev/null 2>&1,或在做定时执行脚本时,把屏幕输出定向到指定文件里
2) 当然也可以开启邮件服务,不过最好不做,因为邮件服务会带来安全问题
3) 优化系统,加定时清理任务,如find /var/spool/clientmqueue/ -type f -mtime +30|xargs rm -f
centos5 sendmail 临时队列目录/var/spool/clientmqueue
当定时任务结尾不加>/dev/null 2>&1的时候,上述目录就会存在大量小文件,sendmail服务不启动的情况下,这些小文件会大量消耗inode,从而造成"No space left on device"的问题。
补充:
centos6有postfix的服务。
- centos5 sendmail临时队列目录 /var/spool/clientmqueue
- centos6 postfix 临时队列目录 /var/spool/postfix/maildrop
默认定时任务执行时会给root发邮件,如果邮件服务不开,就会把邮件堆到上述目录。
当定时任务结尾不加>/dev/null 2>&1的时候,上述目录就会存在大量小文件,sendmail/postfix服务不启动的情况下,这些小文件会大量消耗inode,从而造成"No space left on device"的问题。
[root@oldboy ~]# service postfix status master is stopped