Categories: Shell

2024年Cron任务完整指南

这是一份在 Linux 上创建、运行和调试 Cron 任务的完整指南。在这篇文章中,你将更深入地了解 cron 的基础知识,探索创建 Cron 任务的语法,以及如何使用 crontab 命令管理你的 Cron 任务。

一、什么是 Cron 任务?

Cron 是一个 Linux 程序,允许用户安排一个软件片段的执行,通常以 shell 脚本或编译后的可执行文件的形式。当你有一个需要按固定时间表运行的任务或需要自动化重复任务(如下载文件或发送邮件)时,通常使用 Cron。

在最基本的层面上,Cron 任务是写入一个叫做 cron 表 的表中的条目,也简称为 crontab。这个条目包含一个调度和一个要执行的命令。cron 守护进程crond在 crontab 中寻找条目,以确定应该运行哪些作业,以及根据指定的调度何时运行它们。

注意:下面的示例在 Ubuntu 操作系统上运行。不同的 Linux OS 可能使用不同的包管理器,但所有其他命令都将以相同的方式工作。

二、Cron 任务是如何工作的?

大多数标准的 cron 安装包含两个命令:

  • croncrond,这是运行调度工具的守护进程
  • 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 命令,你应该能看到它。

三、Cron 任务调度语法

一个基本的 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 是一个用于测试调度语法并将它们翻译成简单英语的方便网站。

四、管理Crontab列表

一旦 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 任务时可能遇到的一些问题的概述。

调度错误

如果你以前没有使用过它,很容易在 cron 语法中犯错误。也许你把语法的分钟和小时部分调换了位置。再次,你可以随时使用 crontab.guru 网站来验证你的语法是否正确。

环境变量

另一个常见的问题是,你的 shell 脚本在你从命令行运行时工作得很好,但似乎无法从 cron 条目运行。如果你的脚本调用了任何环境变量,这可能就是原因。Cron 不从 .bashrcbash_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 任务。

系统日志

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系统中如飞书、钉钉等等。

4.5
40
Linux Dig命令详解
SSH的配置文件详解
嘻嘻

嘻嘻IT: 笔者是一个工作七八年的程序猿老鸟,从事涉及的技术栈主要包括PHP、Linux、Devops等,喜欢研究新技术,尝试新技术,提升技术自动化和开发效率,致力于write less,do more! 技术每年都会层出不穷,领域划分的越来越细,不可能学习所有的东西,保持对技术的好奇心,理解技术中核心思想,做一个有深度,有思想的开发!

Recent Posts

2024 Google I/O大会放出AI大招 – 招招要友商的”命”

在谷歌年度开发者大会I/O的尾…

21小时 ago

PHP Composer如何安装?

PHP Composer是PH…

3天 ago

MacOS上Missing xcrun的问题

在使用MacOS进行编程或开发…

3天 ago

CodeGeeX是一款基于大模型的全能AI编程助手

CodeGeeX是一个面向开发…

3天 ago