Linux定时任务crontab详解

Linux定时任务crontab详解

crontab的作用

定时循环任务是由linux上的crond系统服务来控制的,这个系统服务实现是以守护进程的方式实现,守护进程的详解戳文章
linux提供给用户进程控制定时任务的命令为crontab,由crontab设置后实现用户自定义的定时任务;

crontab的设置

crontab的用法

[root@wefang ~]# crontab [-u username] [-l|-e|-r]
选项与参数:
-u : 只有root才能执行这个任务;
-e : 编辑crontab的任务内容(常用);
-l : 查看crontab的任务内容;
-r : 删除所有的crontab任务,若仅要删除一项,用-e去编辑;

crontab的编辑列表

打开一个腾讯云服务器的crontab列表:Linux定时任务crontab详解
可以看到在crontab中配置了三项定时任务,且定时任务的格式都类似;
具体每项代表含义列表如下:

代表意义 分钟 小时 日期 月份 命令
数字范围 0-59 0-23 1-31 1-12 0-7 需要执行的命令

注意:周的0和7都是代表周日的意思
注意到在上图中,除了数字外,还有特殊符号占据了项的内容,特殊符号的含义如下:

特殊字符 代表意义
* 代表任何时刻。就是“每”的 意思,如 * * * * * command,就是在crontab中注册了一个每分钟,每小时,每天,每月每周都发生的command;
用于分隔时段,逗号分隔的数字都会发生。如需要任务在每天8点和12点发生,即命令为 0 8,12 * * * command
- 用于一段持续的时间,如需要在8点到12点每个小时都发生一次,即命令为 0 8-12 * * * command
/n n是一个数字,代表“每隔”n个时间发生一次,如需要五分钟发生一次 ,即命令为 */5 * * * * command

crontab的配置

  • 允许用户使用crontab,一般有如下两个配置,正常情况下保留一个就ok
  1. /etc/cron.allow定义可以使用crontab的账号,不在这个文件内的用户就不能使用crontab;
  2. /etc/cron.deny定义不能够使用crontab的账号,不在这个文件内的用户就可以使用crontab;
  • 用户使用crontab创建完定时任务之后,该项任务就被记录到/var/spool/cron中,且内层目录的文件夹是以用户名作为区分的;
  • crontab的系统配置文件/etc/crontab和/etc/cron.d,一般我都没管过…所以也不是很清楚;

crond进程

crontab命令由crond进程实现,在重新写crontab命令后,要对crond进程重启服务或重新载入配置才ok;
crond的各项操作如表所示:

命令 代表含义
service crond start 启动服务
service crond stop 关闭服务
service crond restart 重启服务
service crond reload 重新载入配置
service crond status 查看服务状态

crontab命令后的> /dev/null 2 > &1的含义

  • 一般定时任务都是作为后台运行> /dev/null用于将crontab后的脚本输出重定向到/dev/null中(丢弃比标准输出),就不会显示在终端;
  • 2 > &1,文件描述符的0,1,2分别代表(标准输入stdin,标准输出stdout,错误输出stderr),标准输出与错误输出默认是输出到终端的,因为目前标准输出已经丢弃,错误输出重定向到标准输出,所以也直接被丢弃啦;

crontab遇过的坑

周末写了个init.sh定时脚本监控一个进程是否启动,若没有启动则将进程拉起,若起了多个进程,则将全部进程干掉,重新拉起,每一分钟执行一次;
init.sh的shell代码如下:

#!/usr/bin/env bash
dir_path='/usr/local/'
file_path=${dir_path}"monitor.py"

monitor_num=`ps -ef | grep monitor | grep -v grep | grep -v vim | wc -l`
log_file=`find  $dir_path -name  "monitor_2019*" | sort -r | head -n 1 | awk -F'/' '{print $NF}'`

echo "init start"

if [ $monitor_num -eq 0 ];then
    now=`date '+%Y-%m-%d %H:%M:%S'`
    #echo "start monitor at:" $now >> $log_file
    #echo $file_path
    /usr/bin/python $file_path &
    if [ $? == '0' ];then
        echo "start monitor success at:" $now >> $log_file
    else
        echo "start monitor fail at:" $now >> $log_file
    fi
elif [ $monitor_num -gt 1 ];then
    ps -ef | grep monitor| grep -v grep| cut -c 9-15| xargs kill -9
    /usr/bin/python $file_path &
    if [ $? == '0' ];then
        echo "start monitor success at:" $now >> $log_file
    fi
    # if montor_num == 1, normal
    # do nothing
fi

配置的crontab命令如下:

* * * * * cd /usr/local/monitor.py; /bin/sh init.sh

配置完了之后,发现每分钟这个init.sh都会被触发一次,然后判断monitor进程没有启动;发现monitor进程没有启动后,启动monitor。但是monitor进程一直没有被拉起,然后就一直拉,也没有效果。
手动执行了一下init.sh脚本,发现monitor进程直接被拉起,也没见什么异常,说明init.sh脚本应该没什么问题;
最后定位到问题,是因为没有在init.sh脚本中加入路径:

export PATH=$PATH:/usr/bin/:/sbin/:/usr/sbin/:/bin/

加入了路径之后就ok啦,一切符合预期要求,测试通过,以后如果遇到这样同样的问题,要考虑下,是否是脚本的路径问题,最好都配置一个全路径,就再也不会出错了。

上一篇:Linux 定时器设置


下一篇:正则表达式清理日志