Cron 定时任务


目录

简介

Cron 是一个用来执行定时任务的工具,可以在指定的时间自动执行重复性任务。

它的核心是 cron 守护进程,名为 crond。它在后台每分钟运行一次,检查是否有需要在当前时间执行的计划任务。

下面命令可以查看 cron 守护进程,是否正常运行。

# Ubuntu / Debian
$ sudo systemctl status cron
# or
$ ps aux | grep cron

# rockyOS / RHEL
$ sudo systemctl status crond
# or
$ ps aux | grep crond

crontab

crond 检查的定时任务,保存在 crontab 文件。该文件的每一行代表一个单独的任务,包含何时运行该任务,以及所要执行的命令。

crontab 分成两个级别:用户个人的crontab,系统的 crontab。前者由用户本人编辑,后者只能由根用户编辑。

系统的 crontab 存放在/etc/crontab(或目录/etc/cron.d/),以及一系列特殊目录之中:/etc/cron.daily、/etc/cron.hourly、/etc/cron.weekly和/etc/cron.monthly。

crontab本身也是一个命令,下面的命令可以检查现有的 cron 任务。

# 当前用户的 cron 任务
$ crontab -l

# 根用户的 cron 任务
$ sudo crontab -l

# 某个指定用户的 cron 任务
$ sudo crontab -u [USERNAME] -l

cron 任务的语法

crontab 文件的每一行,代表一个 cron 任务。它由多个字段组成,字段之间使用空格或制表符分隔。

cron 任务的基本语法如下。

minute hour day_of_month month day_of_week command_to_execute

各个字段的含义如下。

crontab 还允许使用通配符。

crontab 还提供一些快捷字符串。

crontab 文件中,以“#”符号开头的行表示注释。

以下是一些示例。

此外,还有几个特殊字母。

L 表示 Last,仅适用于“月份中的某一天”和“星期几”。

0 4 L * * command -每月最后一天凌晨 4 点
0 4 * * 5L command -每月最后一个星期五凌晨 4 点

W表示 weekday,即该月内最近的一个工作日,仅适用于“月份中的某一天”。

0 4 15W * * command -每月 15 日最近的工作日(周一至周五)凌晨 4 点

#表示该月的第几个,仅适用于“星期几”。

0 4 * * 5#2 -每月第二个周五凌晨 4 点

环境变量

cron 任务在非交互式、非登录 Shell 环境中运行,这意味着它们可能无法访问与手动运行命令时相同的环境变量。

这就是说,cron 任务不会自动继承用户或系统的环境变量或路径。这可能会导致 cron 作业失败,无法找到可执行文件或脚本。解决方法是在 crontab 文件中显式设置 PATH 环境变量。

PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

不过,为了便于调试,建议始终在 cron 任务中使用绝对路径。

除了PATH环境变量,还可以设置SHELL环境变量,指定 cron 使用的 Shell。

SHELL=/bin/sh

上面示例设定执行 cron 任务时,使用 Bash。

添加其他环境变量,都是这种格式。

result="HELLO WORLD"

上面示例添加了环境变量result,值为“HELLO WORLD”。

cron 任务管理

个人任务

创建或编辑用户的 crontab 文件,使用下面的命令。

# 编辑当前用户的 cron 任务
$ crontab -e

# 编辑根用户的 cron 任务
$ sudo crontab -e

# 编辑指定用户的 cron 任务
$ sudo crontab -u [USERNAME] -e

上面的命令会打开系统默认文本编辑器,对用户的 crontab 文件进行编辑。

另一种方法是手动把 cron 任务添加到系统的/etc/cronjob文件,或者在/etc/cron.d/目录中创建一个新文件。建议使用后者,因为/etc/cronjob有可能在系统更新时被覆盖。

更新上面两个位置的 crontab 文件时,每个任务需要在第六个字段添加某个用户名,表示该任务运行在哪个用户名下。

* * * * * user command

定期运行脚本还有一种方法,就是使用/etc/cron.*目录,将脚本保存在以下目录之一的里面,就可以直接以根用户的身份运行该任务。(为了确保脚本可以运行,最好打开脚本的运行权限。)

添加 cron 任务,只需在 crontab 文件中添加一个新行即可。例如,备份脚本 backup.sh 每天凌晨 3:00 运行,就是添加下面的内容。

0 3 * * * /home/linuxiac/backup.sh

编辑完成后,保存并退出编辑器。cron 服务会自动检查 crontab 文件,因此无需在更改后重新启动 cron 进程。

crontab -e还会在保存和退出文件时,自动检查语法,防止意外输入无效的 cron 任务。

删除某个 cron 任务时,只要删除那一行即可。

如果想要删除所有的 cron 任务,只要删除 crontab 文件即可,也可以使用命令行参数-r。

# 删除当前用户的所有 cron 任务,而且没有提示
$ crontab -r

上面的命令会删除当前用户的 crontab 文件(即删除所有 cron 任务),而且不会出现任何确认提示,因此请小心使用。

如果希望删除前出现确认提示,则可以使用命令行参数-i。

# 删除当前用户的所有 cron 任务之前,会有确认提示
$ crontab -i -r

下面是删除根用户和其他用户的 cron 任务。

# 删除根用户的所有 cron 任务
$ sudo crontab -r

# 删除特定用户的所有 cron 任务
$ sudo crontab -u USERNAME -r

系统任务

创建系统级别的 cron 任务,需要直接编辑/etc/crontab文件。

0  2  *  *  * root /usr/bin/find /var/log/myservice -type f -name '*.log' -delete

上面示例设定在每天凌晨2:00,从/var/log/myservice目录删除所有带有扩展名为.log的文件。

它的格式与用户级别的 cron 文件有一个区别,就是在最初表示时间的五个字段后面,多了一个字段,表示执行任务的用户帐户,本例为root。

直接编辑/etc/crontab文件有两个缺点。(1)它不提供语法检查,增加了出错的风险。(2)它会影响整个系统,使用时需要非常谨慎。

列出所有的系统级别 cron 任务,需要查看以下所有文件和目录。

cron 任务的日志

cron 任务执行的 stdout 输出不会被记录,必须添加到命令或脚本本身。

0 4 * * 5L command -v >> /var/logs/command.log

简单的执行记录,可以查看系统日志。Ubuntu / Debian 是/var/log/syslog或者/var/log/auth.log,RHEL/RHEL 是/var/log/cron,可以使用 grep 命令过滤日志。

$ sudo grep -i cron /var/log/syslog /var/log/auth.log

参考链接


版本号 #1
由 壳壳虫 创建于 2024-04-12 22:50:15 UTC
由 壳壳虫 更新于 2024-09-07 00:29:46 UTC