Linux系统定时任务Cron(d)

1. Cron(d)介绍

Cron是Linux系统中以后台进程模式周期性执行命令或指定程序任务的服务软件。默认情况下,安装完Linux系统之后,Cron系统软件便会启动,服务对应的进程名字为CrondCrond服务会定期(默认每分钟一次)检查系统中是否有需要执行的定时任务工作计划。如果有,便会根据其预先设定的定时任务规则自动执行该定时任务工作。

注意:Cron定时任务执行的最快频率是每分钟一次,因此如果需要以秒为单位执行的计划任务,可以写shell脚本,然后作为守护程序执行。以下是一个每秒钟执行一次任务的脚本:

[root@localhost ~]# cat cron.sh 
while true
do
echo "I am people."
sleep 1
done

Cron的主要任务就是文件数据备份。Cron工具可以很好地帮我们完成需要重复的、周期性地、自动备份等运维工作。

2. Linux系统定时任务Cron(d)

在Linux系统中,Cron是定时任务的软件名,Crond是服务进程名,而Crontab命令是用来设置定时任务规则的配置命令。

Cron定时任务可以人工划分为用户定时任务计划系统定时任务计划两类。

2.1 用户定时任务计划

Crond服务在工作时会以分钟为单位查看/var/spool/cron路径下以系统用户命名的定时任务文件,确定是否有需要执行的任务计划。如果有,就会把定时任务调度到内存中执行。这部分文件就被称为用户定时任务文件,使用crontab命令编辑的文件最终会以当前用户名作为文件名存在于/var/spool/cron路径下。

如果是系统管理员或某个普通用户定期要做的任务工作,例如每隔5分钟与互联网上的时间服务器进行一次时间同步,每天晚上0点备份网站站点数据以及数据库数据,就可以使用crontab命令配置在/var/spool/cron路径下。

2.2 系统定时任务计划

Crond服务在工作时除了查看/var/spool/cron路径下的定时任务文件外,还会查看/etc/cron.d目录以及/etc/anacrontab下的文件内容,里面通常是每天、每周或每月需要执行的任务,如果有需要执行的任务就会执行,系统定时任务的路径通常如下:

[root@localhost ~]# ls -l /etc|grep cron
-rw-------.  1 root root    541 Aug 24  2016 anacrontab
drwxr-xr-x.  2 root root   4096 Mar  8 09:55 cron.d         #<==系统定时任务的目录。
drwxr-xr-x.  2 root root   4096 Mar  8 09:55 cron.daily     #<==按天轮询配置的目录。
drwxr-xr-x.  2 root root   4096 Mar  8 09:54 cron.hourly    #<==按小时轮询配置的目录。
drwxr-xr-x.  2 root root   4096 Mar  8 09:55 cron.monthly   #<==按月轮询配置的目录。
drwxr-xr-x.  2 root root   4096 Sep 27  2011 cron.weekly    #<==按周轮询配置的目录。

特别注意:系统路径下的定时任务配置格式与前文讲解的用户定时任务的配置格式是不同的。

Crond服务除了执行用户定时任务计划(/var/spool/cron目录)以外,还会周期性地自动执行与操作系统相关的定时任务工作,例如轮询系统日志、备份系统数据、清理系统缓存等,这些任务无需我们人为干预。示例代码如下:

[test@localhost ~]$ ls -l /var/log/messages*    #<==Linux系统的日志被自动轮询,以时间结尾。
-rw-------. 1 root root 470941 97 09:06 /var/log/messages
-rw-------. 1 root root  77868 824 19:35 /var/log/messages-20230825
-rw-------. 1 root root 153778 831 17:27 /var/log/messages-20230901
[test@localhost ~]$ ls -l /var/log/secure*
-rw-------. 1 root root  6969 97 09:07 /var/log/secure
-rw-------. 1 root root 17640 825 08:25 /var/log/secure-20230825
-rw-------. 1 root root  6494 91 08:52 /var/log/secure-20230901

类似于上述的日志轮询工作就是由系统自身来完成的,不需要系统管理员来设置。

2.3 服务设置

systemctl start crond.service    # 开启
systemctl stop crond.service     # 停止
systemctl status crond.service   # 查看状态

systemctl disable crond.service  # 关闭自启动
systemctl enable crond.service   # 开启自启动

3. 用户定时任务Cron(d)使用说明

3.1 crontab定时任务编辑命令语法

在Linux运维工作中,通常使用crontab命令编辑定时任务。

  • crontab的相关参数及说明
参数 含义 示例
-l(小写L) 查看定时任务内容。提示:l为list缩写 crontab -l
-e 编辑定时任务内容,提示:e 为edit缩写 crontab -e
-i 删除定时任务内容,删除前会提示确认 crontab -ri
-r 删除定时任务内容 crontab -r
-u 指定使用的用户执行任务 crontab -u test -l

【特别强调】

使用crontab命令编辑的文件实际上就是在操作“/var/spool/cron/当前用户名”这样的文件。-i-r参数在生产中很少使用。

  • crontab命令参数的等效命令:
crontab -l            <==>  cat /var/spool/cron/root
crontab -e            <==>  vim /var/spool/cron/root
crontab -u root -l  <==>  cat /var/spool/cron/root

3.2 使用定时任务权限及配置文件说明

文件 说明
/etc/cron.deny 该文件中所列的用户不允许使用crontab命令,不常用
/etc/cron.allow 该文件中所列的用户允许使用crontab命令,优先于/etc/cron.deny
/var/spool/cron/ 所有用户的Cron配置文件默认都存放在此目录中,文件名以用户名命名。以root用户为例,执行crontab -e就等同于vim /var/spool/cron/root,而执行crontab -l就等同于执行cat/var/spool/cron/root

3.3 以用户定时任务crontab命令编辑内容格式

默认情况下,待用户建立定时任务规则之后,该规则所记录的对应配置文件将会存在于/var/spool/cron中,其crontab配置文件对应的文件名与登录的用户名应一致,例如,root用户的定时任务配置文件为/var/spool/cron/root

利用crontab命令编写定时任务的书写格式很简单,规则一般可分为6个段(每个段之间均通过空格来分隔),前5段为时间设定段,第6段为所要执行的命令或脚本任务段。

  • 用户定时任务编写基本格式如下:
# 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
# |  |  |  |  |
# *  *  *  *  *  (command to be executed)

共六列:
第一列:分 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
第六列:要执行的任务命令或程序
  • crontab命令编辑的用户定时任务时间段说明
含义 取值范围
1 分钟 00~59
2 小时 00~23
3 01~31
4 01~12
5 星期 0~7(0和7都表示星期日)

在使用crontab命令编辑的用户定时任务的语法中,除了时间段以外,还会包含很多特殊字符应用,用户定时任务编写语法中的特殊字符及含义:

特殊符号 含义
* *号,表示任意时间都,实际就是“每”的意思。
例如,00 23 * * * cmd表示每月每周每日的23:00都执行cmd任务。
需要注意的是,各个时间位上的“*”表示每,如果位上是“*”就是该位上时间的取值范围,例如:小时上的“*”等价于00~23。
经验技巧:定时任务规则如果间隔单位到小时,那么口述时就最多提到每天。分位上的“*”就等价于00~59,表示每分
- 减号,表示分隔符,表示一个时间范围、区间段,如17~19点,每天的17、18、19的00分执行任务。00 17-19 * * * cmd。就是17、18、19点整点分别执行的意思
, 逗号,表示分隔时段的意思。30 17,18,19 * * * /bin/sh /scripts/test.sh表示每天17、18和19点的半点时刻执行/scripts/test.sh脚本。也可以与“-”结合使用
/n n代表数字,即“每隔n单位时间”,例如:每10分钟执行一次任务可以写成“*/10 * * * * cmd”,其中,“/10,*”的范围是0~59,因此,也可以写成0-59/10。

3.4 crontab命令编辑的定时任务依赖服务说明

crontab命令编辑的定时任务依赖于crond服务,下面来看一下它的运行情况,示例代码如下:

[root@localhost ~]# systemctl status crond.service  #<==查看Cron定时任务服务启动状态。
● crond.service - Command Scheduler  
#下面的enabled说明开机Crond为自启动状态,running为当前启动状态。
    Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
    Active: active (running)since Thu 2020-10-08 01:56:12 CST; 41min ago
Main PID: 13189 (crond)
    CGroup: /system.slice/crond.service
            └─13189 /usr/sbin/crond -n
......

特别强调:

1)在编辑定时任务文件之后,无须重启定时任务,Crond会自动检查更改的变化。

2)当定时任务不能正确执行时,请查看定时任务日志文件(/var/log/cron)以获取故障信息。

4. 用户定时任务Cron实例说明

# 命令实例1:
*/1 * * * * /bin/sh /scripts/data.sh    # 表示每隔一分钟执行一次/bin/sh/scripts/data.sh程序。

# 命令实例2:
30 3,12 * * * /bin/sh /scripts/test.sh   # 每天凌晨3:30和中午12:30执行一次/scripts/test.sh脚本任务。

# 命令实例3:
30 */6 * * * /bin/sh /scripts/test.sh  # 每隔6个小时的 半点时刻 执行一次/scripts/test.sh脚本任务。

# 命令实例4:
30 8-18/2 * * * /bin/sh /scripts/test.sh  # 早晨8点到下午18点之间,每隔2小时的 半点时刻 执行一次脚本任务。

# 命令实例5:
30 21 * * * /application/apache/bin/apachectl graceful  # 每晚的21:30重启Apache

# 命令实例6:
45 4 1,10,22 * * /application/apache/bin/apachectl graceful   # 表示每月1、10、22日的凌晨4:45分重启一次Apache

# 命令实例7:
10 1 * * 6,0 /application/apache/bin/apachectl graceful   # 表示每周六、周日的凌晨1:10分重启一次Apache

# 命令实例8:
0,30 18-23 * * * /application/apache/bin/apachectl graceful  # 表示在每天18:00至23:00之间每隔30分钟重启一次Apache

# 命令实例9:
00 */1 * * * /application/apache/bin/apachectl graceful   # 表示每隔一小时整点重启一次Apache

# 命令实例10:
00 11 * 4 1-3 /application/apache/bin/apachectl graceful  # 表示4月的每周一到周三的上午11点整重启一次Apache

4.1 定时任务的书写操作步骤

1)先在命令行调试成功。

2)再将命令复制到定时任务配置里。

3)然后保存,并使用tail -f测试观察结果。

4)如果遇到问题,则可根据输出以及定时任务日志/var/log/cron文件内容排错。

  • 范例:让服务器时间每5分钟与互联网时间做一次同步。
[root@localhost ~]# crontab -l|tail -3
#time sync by test at 20180429
*/5 * * * * /usr/sbin/ntpdate ntp1.aliyun.com &>/dev/null  #<==主时间同步配置。
*/5 * * * * /usr/sbin/ntpdate ntp3.aliyun.com &>/dev/null  #<==辅助时间同步配置。

CentOS7 默认没有安装ntpdate命令,需要事先执行yum安装,命令是:yum install ntpdate -y

服务器的时间同步很重要,因此,在工作中最好是配置两个不同地址的同步任务。

4.2 生产环境下的定时Cron书写要领

  • 要领1:为定时任务规则加上必要的注释

书写定时任务规则时应尽可能地加上注释(最好是英文注释),这是个很好的运维习惯和规范。

例如,什么人,在什么时间,因为谁(需求方),做了什么定时任务计划。 带注释的定时任务示例代码如下:

[root@localhost scripts]# crontab -l
#backup site dir by test at 202305           #<==清晰的注释,是专业、资深运维的习惯。
00 00 * * * /bin/sh /server/scripts/bak.sh >/dev/null 2>&1
  • 要领2:所有的定时任务尽量都以脚本的形式执行

如果定时任务计划直接使用Linux命令执行,不但看着不规范,而且也很容易出错,特别是带系统时间变量(如果含有“%”,则必须要转义,即“%”)的任务命令,如果能以文件的形式书写,则可以减少很多潜在的错误,并提升效率、规范,这是一个好习惯。

在定时任务中执行命令也会有一些限制,如时间变量问题,多个重定向命令混用问题等,示例代码如下:

[root@localhost scripts]# crontab -l
#backup site dir by test at 201805 
00 00 * * * /bin/sh /server/scripts/bak.sh >/dev/null 2>&1 #<==写成脚本文件执行最佳。
[root@localhost scripts]# cat bak.sh  #<==脚本文件内容如下。
cd /var/www/&&\
/bin/tar zcf /data/bak_$(date +%F).tar.gz ./html
  • 要领3:在执行的Shell脚本前加上/bin/sh

要确保Cron对应的执行者有访问Shell脚本所在目录的权限,并且可执行该Shell脚本(可用chmodchown修改脚本权限和所有者)。当然,最佳方法是在要执行的任务脚本前加上/bin/sh,然后执行,否则就有可能会因为忘了为脚本设定执行权限,而无法完成当次任务执行计划。本条要领是一个经验型的好习惯。执行其他语言的脚本也要加上对应语言的解释器,以下是相应的执行方法示例。

规范的Shell脚本定时任务执行方法:/bin/sh/server/scripts/bak.sh

规范的Perl脚本定时任务执行方法:/usr/bin/perl/server/scripts/bak.sh

规范的Python脚本定时任务执行方法:/usr/bin/python/server/scripts/bak.py

  • 要领4:定时任务中在命令或脚本的结尾加上 >/dev/null 2>&1

定时任务(一般是脚本任务)规则的结尾最好加上“>/dev/null 2>&1”,如果需要打印日志,则可以追加到指定的日志文件里(此时不要与/dev/null同时存在),总之,定时任务计划脚本的结尾尽量不要留空。因为在默认情况下,定时任务每一次执行完毕之后,都会向对应的用户发邮件,如果不加将输出(正确或错误)定向到空的内容(>/dev/null 2>&1),则可能会由于系统未开启邮件服务而导致邮件临时目录文件数猛增的隐患发生,大量小文件占用磁盘Inode节点数量(每个文件占一个Inode),以致磁盘Inode写满而无法再写入正常数据(故障提示:no space left on device.)的故障发生。

在“>/dev/null 2>&1”中,“>”表示重定向,“/dev/null”为特殊的字符设备文件,表示黑洞设备或空设备。“2>&1”表示让标准错误和标准输出一样,本命令的意思是将前面脚本的正常和错误输出都重定向到/dev/null,也就是什么都不输出

下面三种让标准错误和标准输出都重定向到空的写法是等价的:

>/dev/null 2>&1  
>1>/dev/null  2>/dev/null 
>&>dev/null
  • 要领5:在指定用户下执行相关定时任务

需要root权限执行的任务可以登录到root用户下然后进行设置,如果执行任务不需要root权限,则可以登录到普通用户下(也可以直接在root下通过命令crontab-u test -e直接设置)进行设置。这里需要特别注意不同用户的环境变量问题,如果是调用了系统环境变量,例如/etc/profile等文件下的变量(如生产场景中Java程序的定时任务计划),那么最好是在程序脚本中将用到的环境变量重新export下。

  • 要领6:生产任务计划程序中不要随意打印输出信息

在开发定时任务程序或脚本时,调试好脚本程序之后,应尽量将Debug及命令输出的内容信息屏蔽掉,如果确实需要输出日志,则可定向到指定的日志文件里,以避免随意输出不做重定向,从而导致系统垃圾的产生。

例如,打包时喜欢用tar命令的zcvf这几个参数。其中的v参数就是用于查看打包信息的。在做定时任务计划时,命令里就不要再带这个参数了。

  • 要领7:定时任务执行的脚本要存放到规范路径下

定时任务执行的脚本要存放到规范路径下,其实,系统中所有的脚本存放都要有规范,这里推荐统一使用/server/scripts作为脚本的存放路径。

  • 要领8:配置定时任务要规范操作过程,减少出错

配置定时任务时,规范的操作过程具体如下。

1)尽量先在命令行测试成功,然后将成功的命令复制到脚本里,新手要在各个细小环节减少出错的机会。

2)然后执行测试脚本,测试成功后,将执行脚本的命令完整复制到定时任务配置里,尽量做到少手动输入命令。

3)先在测试环境下进行测试,然后在正式环境下规范部署。

4)要有检验任务是否正确执行的手段,例如,检查/var/log/cron日志文件,如果任务执行计划频率较低,也要想法确保任务的可执行性,此处可见下文调试定时任务的技巧。

  • 要领9:定时任务脚本中程序命令及路径尽量使用全路径

定时任务脚本中,程序命令及路径应尽量使用全路径,这是个防止定时任务执行错误的好习惯,否则可能会导致命令行操作命令及执行脚本是正常的,但是放到定时任务中却无法正确执行的问题。当然,对于命令,除了写全路径之外,还可以在脚本中重新定义PATH环境变量,示例代码如下:

[root@localhost scripts]# crontab -l
#backup site dir by test at 202305 
00 00 * * * /bin/sh /server/scripts/bak.sh >/dev/null 2>&1 #<==/bin/sh命令使用全路径。
[root@localhost scripts]# cat bak.sh  #<==任务脚本内容如下。
cd /var/www/&&\
/bin/tar zcf /data/bak_$(date +%F).tar.gz ./html #<==/bin/tar备份命令使用全路径。

重新定义PATH环境变量的方法如下:

[root@localhost scripts]# echo $PATH  #<==打印输出,根据输出选择路径进行重新定义。
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost scripts]# cat bak.sh  #<==脚本内容如下。
export PATH='/sbin:/bin:/usr/sbin:/usr/bin'         #<=重新定义环境变量,包含脚本中所有执行命令所在的路径。
cd /var/www/&&\
tar zcf /data/bak_$(date +%F).tar.gz ./html #<==这里可以取消全路径了。
  • 要领10:时间变量%号要使用反斜线转义

“%”号在Cron任务配置中被认为是newline,需要要用“\”来转义。使用crontab编辑任务时,如果有类似于“date+%F”的时间变量,则必须做如下转义“date+%F”,但是如果是在脚本中编写,那么“%”就不需要转义了。这也是笔者推荐定时任务使用脚本文件来执行的原因之一,定时任务使用命令执行时,执行命令中带有时间变量的写法(不建议使用此法)示例如下:

#tar comment by test at 202305
*/1 * * * * tar zcf /data/bak_$(date +\%F).tar.gz /var/www/html &>/dev/null
  • 要领11:若脚本中调用了系统环境变量,则要重新定义

crontab执行Shell等脚本时只能识别很少的系统环境变量,用户在/etc/profile等文件中定义的普通变量一般是无法被定时任务服务识别的,如果在编写的脚本中需要使用这些环境变量,那么最好是使用export重新声明下该变量,这样脚本才能正常执行。

例如,在调试Java程序任务计划的时候,需要多注意环境变量的问题,务必要将环境变量的定义加到定时任务计划脚本里。Task.sh的作用是执行Java相关的程序,这里需要在脚本中重新定义相关的环境变量,示例代码如下:

[root@localhost ~]# cat /scripts/resin/shell/Task.sh
#!/bin/bash
export JAVA_HOME=/application/jdk1.6  #<==如下三行是安装Java相关环境需要的特殊变量。
export PATH=$JAVA_HOME/bin:$PATH
export SH_HOME=/application/resin/webapps/ROOT/
export LIB=$SH_HOME/WEB-INF/lib
...省略部分...

定时任务的配置结果如下:

#JAVA Shell by test 202307
00 9,14 * * * nohup /scripts/resin/shell/Task.sh & >/app/log.log 2>&1
  • 要领12:出错或无法执行,就检查/var/log/cron日志

4.3 调试Cron定时任务的技巧总结

1) 增加执行任务的频率以调试任务

在调试时,将任务执行频率调快一点,例如,每天执行的任务,可以改为每分钟、每5分钟执行一次,或者以当前时间为准,推迟5分钟以后,看能否执行,而且是不是按照你想要的去执行。如果正常没问题了,那么再改成需要的任务的执行时间。

需要强调一点的是,有些计划任务是不允许频繁执行的。例如,定时向数据库里插入数据,这样的任务就要在测试机上先测试好,然后再部署到正式线上,这样正式工作时出问题的机率就少了。

专业、规范的公司开发和运维人员配置服务器的操作流程至少是:办公室测试环境→IDC机房测试环境→IDC机房正式环境,在不同的环境上测试成功,再到更高级的环境是保障操作人员在正式环境下不出错的关键。

2) 调整系统时间调试任务(不能用于生产环境)

用正确的执行任务的时间测试完成以后,即可修改系统的当前时间,改成任务执行时间的前几分钟来进行测试(或者重启定时任务服务)。例如,定时任务于9:00执行,那么我们可以将系统时间改成8:55分,然后观察是不是正确执行了,当前时间比任务时间建议提前3分钟以上,否则可能就不会执行。

如果是生产环境服务器,则尽量不要修改时间测试,在测试环境下才可以使用这个手段。例如,若是要在周三的2:00执行,则可以将系统时间调整为周三凌晨1:55分查看执行结果。

3) 通过脚本日志输出调试定时任务

要输出调试定时任务,可在脚本中加入日志输出,然后将输出打印到指定的日志中,并观察日志内容结果,以查看是否执行或正确执行。或者像下面一样,将脚本结果定向到一个log文件里。这里使用重定向符号“>”即可,不需要使用“>>”符号,这样日志就不会一直变大,如/app/log.log。示例代码如下:

#study task by test at 20121213
00 9,14 * * 6,0 /bin/sh /server/scripts/test.sh >/app/log.log 2>&1

提示:对于不好查看执行结果的定时任务计划可以这样调试。

也可以在脚本命令中通过参数打印信息输出,然后将输出重定向到指定的文件,示例代码如下:

[root@localhost scripts]## cat tar.sh
cd /
tar zcvf /tmp/etc_$(date +%F).tar.gz ./etc >/tmp/tmp.log 2>&1    #<==加v参数,结尾重定向到文件。

4) 通过Crond定时任务服务日志调试定时任务

查看定时任务服务的日志,可以发现执行的以及不能执行的任务问题所在,示例日志信息如下:

[root@localhost scripts]# tail -f /var/log/cron
Nov 10 11:40:01 localhost crond[2605]: (root)CMD (echo "==" >> /tmp/test.log >/dev/null 2>&1)
Nov 10 11:40:01 localhost crond[2608]: (root)CMD (/usr/sbin/ntpdate pool.ntp.org >/dev/null 2>&1)
Nov 10 11:41:01 localhost crond[2615]: (root)CMD (/bin/sh /server/scripts/echo.sh >/dev/null 2>&1  #print date)
Nov 10 11:42:01 localhost crond[2625]: (root)CMD (/bin/sh /server/scripts/echo.sh >/dev/null 2>&1  #print date)
Nov 10 11:42:01 localhost crond[2627]: (root)CMD (echo "==" >> /tmp/test.log >/dev/null 2>&1)
Nov 10 11:42:01 localhost crond[2628]: (root)CMD (echo + >> /tmp/test.log)
tar.gz ./html

5. crontab生产案例故障分析及解决

故障描述及说明

工作中可能会出现这样的问题:

在保存设置定时任务的规则时,系统提示“No space left on device”,此时用df -h命令检查磁盘,发现还有剩余空间,再用df -i命令检查则显示Inode已被100%占用了,导致系统无法在/var目录下创建文件。因为定时任务配置在/var/spool/cron下,在ext3、ext4文件系统中,每个文件至少要占用一个Inode。

最后,经过检查发现在/var/spool/clientmqueue/下有大量的小文件,执行ls/var/spool/clientmqueue命令查看,很长时间都没能显示出结果,执行cd/var/spool/clientm-queue;rm-f*命令则会自动跳出来,无法实现删除。最后的解决方法是使用命令cd/var/spool/clientmqueue&&ls|xargs rm-f进行清理。

在清理时,如果文件的数量特别多,那么执行ls|xargs rm-f命令也会长时间无反应,不要着急,这是命令正在处理中的正常表现。当然,我们也可以使用更快的删除方法,如直接使用cd/var/spool&&rm-fr clientmqueue删除上级目录,然后执行如下命令:

mkdir clientmqueue && chmod 770 clientmqueue && chown smmsp.smmsp -R /var/spool/clientmqueue

修改回/var/spool/clientmqueue目录在系统中原有的默认权限:

[root@localhost ~]# ls -ld /var/spool/clientmqueue/
drwxrwx--- 2 smmsp smmsp 4096 12-12 13:46 /var/spool/clientmqueue/

故障原因分析

当系统中Crond定时任务执行的程序包含输出内容时,输出内容会以邮件的形式发回给执行任务的用户(默认是root),而sendmail、postfix等mail服务没有启动时,这些输出内容就会在邮件队列临时目录中产生大量很小的文件,导致消耗大量的Inode和block数量(在ext文件系统中,默认情况下格式化block的数量会远大于Inode的数量),一旦Inode数量耗尽,就会导致系统无法写入文件而报出上述错误“No space left on device”。

提示:上述为CentOS5系统中的故障案例,同样适合于CentOS6、CentOS7,只是后两者小文件多的路径改为postfix的临时邮件队列目录了。

预防方法

1)尽量在Cron任务中的命令或脚本中的命令的结尾加上“>/dev/null 2>&1”,或者在写定时执行脚本时,将输出定向到指定文件中(适合于所有情况)。

2)当然也可以开启邮件服务,不过最好不做,因为邮件服务会带来额外的安全问题。

3)添加定时清理任务,比如,将find/var/spool/clientmqueue/-type f-mtime+30|xargs rm-f放入定时任务,每周处理一次(适合于CentOS5),如果是CentOS6或CentOS7,则处理的路径为/var/spool/postfix/maildrop/

6. 定时任务知识逻辑图

Linux系统定时任务Cron(d)_第1张图片

你可能感兴趣的:(边学边记-linux,linux,服务器,运维,centos)