文章目录
这是一份在 Linux 上创建、运行和调试 Cron 任务的完整指南。在这篇文章中,你将更深入地了解 cron 的基础知识,探索创建 Cron 任务的语法,以及如何使用 crontab
命令管理你的 Cron 任务。
Cron 是一个 Linux 程序,允许用户安排一个软件片段的执行,通常以 shell 脚本或编译后的可执行文件的形式。当你有一个需要按固定时间表运行的任务或需要自动化重复任务(如下载文件或发送邮件)时,通常使用 Cron。
在最基本的层面上,Cron 任务是写入一个叫做 cron 表 的表中的条目,也简称为 crontab。这个条目包含一个调度和一个要执行的命令。cron 守护进程crond在 crontab 中寻找条目,以确定应该运行哪些作业,以及根据指定的调度何时运行它们。
注意:下面的示例在 Ubuntu 操作系统上运行。不同的 Linux OS 可能使用不同的包管理器,但所有其他命令都将以相同的方式工作。
大多数标准的 cron 安装包含两个命令:
cron
或 crond
,这是运行调度工具的守护进程crontab
,这是允许你编辑作业的 cron 条目的命令当你从 Linux 的角度谈论一个 daemon(守护进程)时,它是一个在后台运行且非交互式的程序。这意味着该程序不接受任何用户输入,也不向用户显示输出。daemon 这个词历史上在 Unix/Linux 的环境中使用,并非在不同的操作系统中都是通用的术语。
守护进程将在 root 用户下运行。你可以运行以下命令来查看 cron 是否在运行:
$ ps aux | grep cron
看到像这样的输出:
root 617 0.0 0.0 9420 2800 ? Ss 17:00 0:00 /usr/sbin/cron -f
如果你从命令中完全没有接收到任何输出,那么 cron 要么没有运行,要么没有安装。
在 Ubuntu 上,你可以通过运行以下命令快速安装 cron:
$ sudo apt update && sudo apt install cron
如果你使用的不是 Ubuntu,你需要运行你的包管理器的等效命令。
一旦 cron 安装好了,记住要确保它已启用并正在使用 systemd 提供的 systemctl
命令运行:
$ sudo systemctl enable cron
现在,Cron 应该已经在运行,如果你再次运行上面显示的 ps
命令,你应该能看到它。
一个基本的 crontab 条目看起来像这样:
* * * * * /home/user/bin/somecommand.sh
| | | | | |
| | | | | 要执行的命令或脚本
| | | | |
| | | | 一周中的某天(0-6 | 周日-周六)
| | | |
| | | 月份(1-12)
| | |
| | 月中的某天(1-31)
| |
| 小时(0-23)
|
分钟(0-59)
星号 (*) 匹配所有值,所以如果你看一下上面的例子,它指定 /home/user/bin/somecommand.sh 应在 分钟 0-59 和 小时 0-23 在 月中的某天 1-31 在 月份 1-12 在 一周中的某天 0-6 运行 – 或者换句话说 每分钟。
Cron 条目也可以配置为在更复杂的时间运行。如果你想在周一至周五每天运行四次,你可以使用 步进操作符 ( / ) 和 范围操作符 ( – )。
0 */6 * * Mon-Fri /home/user/somejob.sh
该条目将在从午夜开始的每六个小时运行你的命令 – 即 12:00 a.m., 6:00 a.m., 12:00 p.m., 和 6:00 p.m. – 但只在周一至周五。
如果你想深入了解其他复杂的调度示例,crontab.guru 是一个用于测试调度语法并将它们翻译成简单英语的方便网站。
一旦 cron 开始运行,它会每分钟检查以下文件中的 crontab 条目:
* **/etc/crontab**
* **/var/spool/cron/crontabs/$USER** (其中 `$USER` 是当前登录的用户)
第一个文件,/etc/crontab,是一个系统生成的文件,包含设计用于检查以下目录中的 cron 表条目的快捷命令:/etc/cron.hourly
,/etc/cron.daily
,/etc/cron.weekly
,和/etc/cron.monthly
。
你可以通过使用 crontab
命令来实现这一点。从终端,使用以下命令进入你的用户的 crontab 的 编辑 模式:
$ crontab -e
第一次运行这个命令时,操作系统应该会问你想使用哪个编辑器,会出现一个小菜单,像这样:
no crontab for user - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
Choose 1-4 [1]:
选择你喜欢的编辑器。如果你以前从未在 Linux 系统上使用过编辑器,那么就按照建议使用 nano
,因为它大体上是一个易于使用的编辑器。
一旦你做出了选择,你选择的编辑器将打开你的用户的默认 crontab,像这样:
目前,文件是空的,但你现在可以自由地在文件的底部添加一个 Cron 任务条目。
到目前为止,你可能会有这样的印象,cron 似乎是一个相当强大的工具,使用它时不可能不出错任何有经验的系统管理员,如果他们花了一些时间设置 Cron 任务,都会告诉你,Cron 任务会并且确实经常失败,原因多种多样。
以下是你在设置 Cron 任务时可能遇到的一些问题的概述。
如果你以前没有使用过它,很容易在 cron 语法中犯错误。也许你把语法的分钟和小时部分调换了位置。再次,你可以随时使用 crontab.guru 网站来验证你的语法是否正确。
另一个常见的问题是,你的 shell 脚本在你从命令行运行时工作得很好,但似乎无法从 cron 条目运行。如果你的脚本调用了任何环境变量,这可能就是原因。Cron 不从 .bashrc 或 bash_profile 这样的文件中加载变量,所以即使你指定了一个常见的变量,如 $USER
,当 cron 守护进程运行你的作业条目时,该变量是未定义的。你需要要么硬编码你的变量值,要么手动从 .bashrc 这样的文件中加载值。
默认情况下,当你创建一个 shell 脚本时,它没有 执行 权限:
$ touch shell_script.sh
$ ls -als *sh
输出:
0 -rw-rw-r-- 1 user users 0 May 21 13:26 shell_script.sh
文件缺少执行权限。通过运行以下命令给文件赋予可执行权限:
$ chmod +x shell_script.sh
$ ls -als *sh
现在输出看起来像这样:
0 -rwxrwxr-x 1 user users 0 May 21 13:26 shell_script.sh
这应该修复了 cron 需要的缺失的执行权限以便运行脚本。
了解更多linux文件权限的内容查看这篇文章Unix/Linux-文件权限/访问模式
你的脚本可以非常强大,然而当系统资源耗尽时,任何强大的脚本都无法帮助你的 Cron 任务成功运行。不幸的是,防止这种情况的唯一方法是监控你的服务器,查看如可用磁盘空间、可用内存和充足的打开文件等指标。
你可能有一个 cron 条目,它运行的频率很高,并且在几秒钟内成功运行。为了方便讨论,也许你每分钟运行一次脚本。有可能一个外部变量干扰了作业的完成,导致作业需要超过一分钟才能完成。cron 守护进程会愉快地生成你的脚本的更多副本,直到你有一小部分军队,它们都在同时运行,从而消耗系统资源。你需要建立检查,如锁文件,以确保任何时候只有一个副本的脚本在运行。
最后,外部变量是超出你控制范围的。例如,如果你有一个从 REST API 端点拉取信息的脚本,并且你正在查询的端点发生了变化,而没有通知你,你的 Cron 任务可能在你不知情的情况下失败。
Cron 任务可能以多种方式失败的方式后,你可能会想知道如何最好地监控它们。
让我们看一下你有哪些有用的选项来最好地监控你的 Cron 任务。
Cron 自动有一些系统级别的日志记录。
在 Debian 和 Ubuntu 系统中,在 /var/log/syslog
中,cron 守护进程报告它何时开始或重新开始。在基于 Redhat 的系统中,cron 守护进程将同样的信息写入 /var/log/cron
的日志条目。
守护进程还报告它何时运行了你的作业,日志条目如下:
Mar 29 16:00:01 mywebserver CRON[12624]: (user) CMD (/home/user/bin/check-visitors.sh)
不幸的是,cron 并不报告你的脚本的成功或失败。它甚至不能告诉你一个作业是否运行。
你可以直接将所有的测量逻辑写入从 cron 条目运行的脚本中。这将涉及到将事件记录到你自己的日志文件中,或者将你的脚本的退出状态捕获到另一个地方,以便由另一个过程监控。你也可以将任何发送到steddr的错误消息写入另一个错误日志文件。然而,这确实增加了你的脚本的复杂性,因为你需要考虑尽可能多的失败情况。
幸运的是,有一个更简单的选项。是的,你可以通过确保你的每个脚本在出错时都能通知你,或者你可以将所有脚本的输出捕获到特殊的日志文件中。将任务执行的结果发送到IM系统中如飞书、钉钉等等。