## 概述
Cron作业是Linux操作系统中一个基本但功能强大的工具。这些基于时间的工作流程对于系统管理员、开发人员和技术爱好者来说是不可或缺的,可以实现日常任务的自动化。
它提供了一个全面的指南,解释了什么是cron作业,它们是如何工作的,最重要的是,如何使用它们来自动化Linux系统上的重复任务。
## 开始
### Cron是什么?
Cron是Unix类操作系统(包括Linux和macOS)中的一个基于时间的任务调度器。它允许用户安排任务(命令或脚本)在固定的时间、日期或间隔周期性地运行。
它最常用于自动执行系统维护或管理任务,但也可用于需要定期、计划执行命令的任何目的。
### Cron的工作原理
后台的核心组件是名为crond的Cron守护进程。其主要任务是检查计划任务并在指定时间到来时执行它们。
守护进程每分钟唤醒一次,以检查crontab文件或基于目录的配置中的作业。这自然将我们带到Cron的下一个关键方面,它支持其操作设置-它使用的文件和目录。
### Cron文件和目录
> Crontab文件是Cron作业调度系统的核心。`Crontab`代表`cron table`,因为这些文件包含在预定时间运行的命令列表。
Crontab文件中的每一行都表示一个单独的作业,并包含有关何时运行作业的信息,后面是要执行的命令。
从本质上讲,crontab文件有两种:`个人用户拥有的文件`和`系统范围的 /etc/crontab `文件。下面是你应该知道的关于这两个方面的关键细节。
但在此之前,有一些重要的事情需要澄清。属于各个用户的`cron`文件不保存在他们的主目录中,而是在`/var/spool/cron`目录中。同时,系统服务和应用程序的`cron`作业文件通常放在`/etc/cron.d`中。
### 用户Crontab
用户crontabs对系统上的每个用户都是个人的。用户可以使用他们的crontab文件在他们的用户ID下安排任务。
用户crontabs的主要优点是,它们允许单个用户管理其作业计划,而不需要管理权限。
### 全系统Crontab
与特定于用户的crontab文件不同,`/etc/crontab`是系统范围的配置文件。它遵循与用户`crontabs`略有不同的格式,包括一个用户字段,用于指定运行命令的用户帐户。
这允许系统管理员安排作业在任何用户下运行,而无需修改该用户的crontab,从而在跨不同用户帐户的任务管理中实现更大的灵活性。
通常,`/etc/crontab`文件通常用于需要以管理权限运行或对系统操作至关重要的作业。
> 另一个要点是,虽然用户可以编辑他们的crontab条目,但系统范围的crontab只能由root用户直接编辑。
### Cron目录
除了crontab文件外,大多数Linux系统还包括一组目录,cron会扫描这些目录以查找计划的作业:`/etc/cron.daily`、`/etc/cron.hourly`、`/etc/cron.weekly`和`/etc/cron.monthly`。
这些目录允许更直接地调度需要定期运行的任务,而无需在crontab中指定确切的时间。
放置在这些目录中的可执行文件和可执行文件分别每天、每小时、每周或每月运行一次。执行这些目录中的脚本的确切时间由`/etc/crontab`中的配置或守护程序的配置文件(通常位于`/etc/cron.d/`中)确定。
### Cron语法基础
Cron作业由Cron文件(crontab)中的一行文本定义。每一行由一系列由空格或制表符分隔的字段组成,后面是待执行的命令或脚本。
Cron作业的基本语法如下:
```ts
minute hour day_of_month month day_of_week command_to_execute
```
![](https://img.kancloud.cn/d0/a4/d0a4cabcea858d2e116b94dad640a0ba_1070x503.png)
*Cron Job的结构*
让我们深入了解每个组成部分:
- **分钟(0-59)**:此字段指定命令运行的分钟。它可以是0到59之间的值。例如,将其设置为0将在小时开始时运行命令。
- **小时(0-23)**:小时字段以24小时格式指定。它决定在一天中的哪个时间执行命令。例如,将其设置为14将在下午2点运行命令。
- **月份中的天(1-31)**:此字段指定命令将运行的月份中的日期。它可以是1到31之间的任何值,具体取决于月份的天数。例如,将此设置为1将在每个月的第一天运行命令。
- **月份(1-12)**:月份字段确定命令将在哪个月份执行。它可以是从1(1月)到12(12月)的值。例如,将其设置为12将在12月执行命令。
- **星期中的天(0-6)**:此字段指定应运行命令的星期几。它可以是0(星期日)到6(星期六)之间的值。例如,将其设置为5将在每个星期五运行命令。
- **命令或脚本**:最后,命令或脚本字段是指定cron作业应该执行的操作的地方。这可以是Cron守护程序将在指定时间执行的任何命令或脚本文件的路径。
### Cron中的特殊角色
Cron语法还支持特殊字符来指定更复杂的调度模式。
* **星号(*)**:表示`每`时间单位。例如,小时字段中的`*`表示`每小时`。
* **逗号(,)**:允许指定值列表。例如,`day_of_week`字段中的`1,3,5`表示`在星期一、星期三和星期五运行`。
* **连字符(-)**:指定值的范围。例如,小时字段中的`9-17`表示`从上午9点到下午5点的每小时`。
* **斜杠(/)**:指定增量。例如,分钟字段中的`*/10`表示`每10分钟`。
除此之外,cron作业还具有特殊的快捷字符串,可以替换时间和日期的五个字段。这些快捷方式提供了一种快速的方法来指定相同的明细表,否则需要数字表示。
### Cron作业何时开始?
当cron作业运行时,它在受限环境中运行,这意味着它不会自动继承用户或系统的环境变量或路径。这可能会导致cron作业失败的问题,因为它无法找到必要的可执行文件或脚本,由于未定义或不正确的路径。
有鉴于此,您可以显式地在crontab文件中设置PATH环境变量,以处理cron作业中的路径。这会告诉cron守护进程在哪里查找可执行文件。举例来说:
```
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
```
在crontab文件的开头添加这一行可以确保下面的所有cron作业都将在这些目录中搜索可执行文件。
但是,考虑到并遵循最佳实践,我们建议**始终指定cron作业中所有可执行文件和脚本的绝对路径**,以避免任何歧义和潜在错误。
此外,在依赖自动执行之前,请使用crontab中定义的相同路径和环境设置手动运行脚本或命令,以确保它们按预期工作。
## 设置和管理Cron作业
现在让我们放下理论。你已经具备了关于Cron作业如何工作及其组件的所有基本知识。是时候进入令人兴奋的部分:`创建Cron作业任务了`。
### 创建用户的Cron作业
要创建或编辑您的用户的crontab文件,请在终端中使用以下命令:
```
crontab -e
```
这是用户创建和编辑cron作业的标准方式。当执行时,它通过在为您的系统设置的默认文本编辑器(如Vi、Nano或其他编辑器)中打开用户的crontab文件,为运行该命令的用户编辑cron作业。
如果这是您第一次使用该命令,系统可能会提示您在继续之前选择一个编辑器。
![](https://img.kancloud.cn/b4/39/b4397f53941bbeffca57acf5cd5f33db_930x367.png)
接下来,要添加一个cron作业,只需按照上面解释的语法向crontab文件添加一个新行。例如,我们将通过添加以下行来安排位于用户主目录中的备份脚本`backup.sh`每天在`3:00 AM`运行:
```
0 3 * * * /home/linuxiac/backup.sh
```
![](https://img.kancloud.cn/5f/7b/5f7bae8c463d451a19dc0cc2e47b2b4a_930x506.png)
以`#`符号为前缀并在文件开头注释掉的许多行可以作为设置cron作业的简明指南。如上图所示,在它们后面键入您的。
接下来,保存并退出编辑器。请记住,Cron服务会自动检查crontab文件的更改并相应地应用它们,因此您不需要在进行更改后重新启动它。
最后,值得注意的是,使用`crontab -e`提供了额外的好处,即在保存和退出文件时自动检查语法。Cron将提醒您检测到的任何错误,提供了一个有价值的保护措施,防止意外输入无效的cron作业。
### 创建系统范围的Cron作业
由于`crontab -e`侧重于单个用户crontabs,因此它不是为某些管理任务可能需要的系统范围的Cron配置更改而设计的。
如果是这种情况,直接编辑`/etc/crontab`文件可以为您提供系统范围的crontab功能。与特定于用户的crontab不同,此文件可以包括系统范围的任务,并支持为每个任务指定用户,从而为在不同用户帐户下运行命令提供灵活性。
例如,让我们创建一个系统范围的cron作业,它将`凌晨2:00`从`/var/log/myservice`目录中删除所有扩展名为`.log`的文件。
为此,我们首先使用首选的终端编辑器打开`/etc/crontab`文件:
```
sudo vim /etc/crontab
```
然后我们进入cron作业,它看起来像这样
```
0 2 * * * root /usr/bin/find /var/log/myservice -type f -name '*.log' -delete
```
![](https://img.kancloud.cn/cc/9c/cc9cb43249ae9fcfdf525a2e45bea1e7_1160x563.png)
*创建系统范围的Cron作业*
与用户cron作业不同的是,在最初的五个时间字段之后包含了一个额外的列。此列允许指定将在其下执行作业的用户帐户-在本例中为root。
但是,直接编辑`/etc/crontab`文件有两个主要缺点。首先,这种方法不提供语法检查,增加了出错的风险。
第二个原因是`/etc/crontab`会影响整个系统,不正确的输入可能会产生广泛的影响,可能会影响系统的稳定性或安全性。所以,小心使用。
### 列出用户的Cron作业
要确保已正确调度cron作业,可以使用以下命令显示用户的crontab文件内容:
```
crontab -l
```
![](https://img.kancloud.cn/91/9e/919e819f9a61245baf669a4f41d073b4_944x187.png)
此命令列出为用户计划的所有cron作业,允许您验证或查看要运行的任务集。
### 列出系统范围的Cron作业
正如我们已经知道的,系统范围的Cron作业存储在不同的位置,并未在用户的crontab中列出。要列出系统范围的Cron作业,您需要查看`/etc/crontab`文件和目录`/etc/cron.d/`、`/etc/cron.daily/`、`/etc/cron.hourly/`、`/etc/cron.weekly/`和`/etc/cron.monthly/`。
您可以使用`cat`命令或任何文本编辑器查看这些文件。举例来说:
```
sudo cat /etc/crontab
```
要列出目录的内容,例如`/etc/cron.daily`,用途:
```
ls /etc/cron.daily/
```
![](https://img.kancloud.cn/e9/f7/e9f7f508c25696d7012984f442299802_941x300.png)
### 列出其他用户的Cron作业
如果您拥有超级用户(root)权限,您可以使用crontab命令与`-u`选项后跟用户名和`-l`选项来列出系统上任何用户的Cron作业。例如,要列出名为`bobby`的用户的Cron作业,您可以运行:
```
sudo crontab -u bobby -l
```
此命令对于系统管理员跨多个用户帐户管理cron作业非常方便。
### 编辑Cron作业
要编辑cron作业,与创建类似,请使用以下命令在默认编辑器中打开当前用户的crontab文件:
```
crontab -e
```
打开crontab文件时,导航到包含要编辑的cron作业的行,并根据需要修改计划或命令,然后保存并退出文件。
如果您需要编辑另一个用户(假设您拥有必要的权限)的crontab文件,例如用户“*bobby*”,请使用:用途:
```
sudo crontab -u bobby -e
```
### 删除Cron作业
根据您的目标,您有几种方法可以删除Cron作业。要删除特定的作业,使用`crontab -e`命令打开crontab文件。
从那里,导航到表示要删除的作业的行。删除这一行,将其全部删除。同时,要注意保持所有其他线路相同。然后,保存您的更改并退出编辑器。
但是,如果您希望删除用户的所有计划cron作业,则可以删除用户的crontab文件。此操作将删除所有计划任务,因此应谨慎执行。
打开终端并输入如下所示的命令:
```
crontab -r
```
![](https://img.kancloud.cn/81/7b/817b814cdafdfd2774e58b18dfd7da49_941x270.png)
这将在没有确认提示的情况下删除当前用户的crontab文件,因此请确保在执行它之前要继续。
如果您希望在删除之前收到确认提示,请使用命令`crontab -i`后跟`-r`。这将要求在删除crontab文件之前进行确认。
### Crontab备忘单
为了总结上面讨论的crontab命令的主要选项,它们在下面的表中简要概述。
| 命令 | 描述 |
| --- | --- |
| **crontab -e** | 编辑crontab文件或如果它尚不存在则创建一个。 |
| **crontab -l** | 显示crontab文件的内容。 |
| **crontab -r** | 删除整个crontab文件。 |
| **crontab -u user** | 当与额外选项配对时,此功能使修改或查看用户的crontab文件成为可能,这是专门保留给具有管理员权限的用户的功能。 |
### 如何排查Cron作业
不幸的是,当Cron作业未能运行时,这可能会令人沮丧,并且根据任务的不同可能会有问题。因此,这里是一些基本指南,用于调查此问题的原因。
排查的第一步是确保Cron作业正确定义。验证每个字段是否根据您的要求正确指定。一个常见的错误是语法不正确或误解Cron如何解释特殊字符和范围。
然后,确保Cron守护程序在您的系统上运行。您可以通过运行以下命令来检查这一点:
```
sudo systemctl status cron
```
![](https://img.kancloud.cn/85/f3/85f37ada8bbe4a2060781952e218887a_941x590.png)
确保cron作业尝试运行的脚本或命令具有适当的权限,并且使用绝对路径。Cron作业在具有最小PATH定义的有限环境中运行,因此指定任何命令或脚本的完整路径至关重要。
此外,该文件必须是可执行的,并且可供计划cron作业的用户访问。尝试使用cron作业使用的同一用户帐户从命令行手动运行命令或脚本。
这可以帮助您验证命令在没有cron环境的情况下是否按预期工作。如果命令失败,您将知道问题出在命令或脚本上,而不是cron上。
请记住,cron作业在非交互式、非登录shell环境中运行,这意味着它们可能无法访问与手动运行命令时相同的环境变量。
如果脚本依赖于环境变量,则可能需要在脚本的开头或cron作业定义中显式设置它们。
## Cron作业示例
最后,我们将展示几个cron作业示例,它们几乎涵盖了所有可能的Cron语法情况。把这些作为你自己制作的基础。
| 命令 | 解释 |
|-------------------|------------------------------------------|
| **\* \* \* \* \*** | 每分钟运行一次Cron作业。 |
| **0 \* \* \* \*** | 每小时运行一次Cron作业。 |
| **0 0 \* \* \*** | 每天午夜运行一次Cron作业。 |
| **0 2 \* \* \*** | 每天凌晨2点运行一次Cron作业。 |
| **0 0 15 \* \*** | 每月15日午夜运行一次Cron作业。 |
| **0 0 0 12 \*** | 每周六午夜运行一次Cron作业。 |
| **0 0 \* \* 6** | 每天下午3点从周一至周五运行一次Cron作业。 |
| **0 15 \* \* 1-5** | 每天下午3点从周一至周五运行一次Cron作业。 |
| **\*/5 \* \* \* \*** | 每5分钟运行一次Cron作业。 |
| **0 8-16 \* \* \*** | 每天从早上8点到下午4点每小时准时执行Cron作业。 |
| **0 4 \* \* 2,4** | 每周二和周四凌晨4点运行一次Cron作业。 |
| **@reboot** | 系统启动时运行Cron作业。 |
这些示例提供了各种Cron语法情境的参考,可以作为创建自己Cron作业的基础。
### 最佳实践和技巧
- **在用Cron安排之前手动测试您的脚本**,以确保它们按预期工作。
- **在crontab文件中使用绝对路径**,以避免路径问题。
- **将输出重定向到文件或邮件**,以捕获任何输出或错误进行故障排除(“command > /path/to/logfile 2>&1”)。这样,您可以查看日志文件以查找任何问题。
- **在安排作业时注意系统负载**,特别是如果它们是资源密集型的或如果您在相同的时间安排了许多作业。
### 结论
Cron作业对Linux系统管理至关重要。它们提供了一个强大而多功能的工具,用于调度和自动化任务。
它的美在于它的多功能性和精确性。从以分钟为间隔执行的简单命令到为特定日期和时间调度的复杂脚本,cron可以适应许多需求。
通过用户和系统范围的crontab文件以及用于周期性任务的指定目录,Cron作业为个人用户和系统管理员提供了灵活性,以根据他们特定的需求定制任务调度。
通过利用本文中的见解和示例,您将很好地实现调度成功,提高生产力,并在您的Linux旅程中解锁新的可能性。
对于更多细节,cron和crontab手册页包含有关cron系统如何工作的全面信息和解释。
- 设计模式系列
- 工厂方法模式
- 序言
- Windows程序注册为服务的工具WinSW
- 基础
- 安装
- 开发规范
- 目录结构
- 配置
- 快速入门
- 架构
- 请求流程
- 架构总览
- URL访问
- 容器和依赖注入
- 中间件
- 事件
- 代码层结构
- 四个层次
- 路由
- 控制器
- 请求
- 响应
- 数据库
- MySQL实时同步数据到ES解决方案
- 阿里云DTS数据MySQL同步至Elasticsearch实战
- PHP中的MySQL连接池
- PHP异步非阻塞MySQL客户端连接池
- 模型
- 视图
- 注解
- @SpringBootApplication(exclude={DataSourceAutoConfiguration.calss})
- @EnableFeignClients(basePackages = "com.wotu.feign")
- @EnableAspectJAutoProxy
- @EnableDiscoveryClient
- 错误和日志
- 异常处理
- 日志处理
- 调试
- 验证
- 验证器
- 验证规则
- 扩展库
- 附录
- Spring框架知识体系详解
- Maven
- Maven和Composer
- 构建Maven项目
- 实操课程
- 01.初识SpringBoot
- 第1章 Java Web发展史与学习Java的方法
- 第2章 环境与常见问题踩坑
- 第3章 springboot的路由与控制器
- 02.Java编程思想深度理论知识
- 第1章 Java编程思想总体
- 第2章 英雄联盟的小案例理解Java中最为抽象的概念
- 第3章 彻底理解IOC、DI与DIP
- 03.Spring与SpringBoot理论篇
- 第1章 Spring与SpringBoot导学
- 第2章 Spring IOC的核心机制:实例化与注入
- 第3章 SpringBoot基本配置原理
- 04.SprinBoot的条件注解与配置
- 第1章 conditonal 条件注解
- 第2章 SpringBoot自动装配解析
- 05.Java异常深度剖析
- 第1章 Java异常分类剖析与自定义异常
- 第2章 自动配置Url前缀
- 06.参数校验机制与LomBok工具集的使用
- 第1章 LomBok工具集的使用
- 第2章 参数校验机制以及自定义校验
- 07.项目分层设计与JPA技术
- 第1章 项目分层原则与层与层的松耦合原则
- 第2章 数据库设计、实体关系与查询方案探讨
- 第3章 JPA的关联关系与规则查询
- 08.ORM的概念与思维
- 第1章 ORM的概念与思维
- 第2章 Banner等相关业务
- 第3章 再谈数据库设计技巧与VO层对象的技巧
- 09.JPA的多种查询规则
- 第1章 DozerBeanMapper的使用
- 第2章 详解SKU的规格设计
- 第3章 通用泛型Converter
- 10.令牌与权限
- 第1章 通用泛型类与java泛型的思考
- 常见问题
- 微服务
- demo
- PHP中Self、Static和parent的区别
- Swoole-Cli
- 为什么要使用现代化PHP框架?
- 公众号
- 一键部署微信公众号Markdown编辑器(支持适配和主题设计)
- Autodesigner 2.0发布
- Luya 一个现代化PHP开发框架
- PHPZip - 创建、读取和管理 ZIP 文件的简单库
- 吊打Golang的PHP界天花板webman压测对比
- 简洁而强大的 YAML 解析库
- 推荐一个革命性的PHP测试框架:Kahlan
- ServBay下一代Web开发环境
- 基于Websocket和Canvas实现多人协作实时共享白板
- Apipost预执行脚本如何调用外部PHP语言
- 认证和授权的安全令牌 Bearer Token
- Laradock PHP 的 Docker 完整本地开发环境
- 高效接口防抖策略,确保数据安全,避免重复提交的终极解决方案!
- TIOBE 6月榜单:PHP稳步前行,编程语言生态的微妙变化
- Aho-Corasick字符串匹配算法的实现
- Redis键空间通知 Keyspace Notification 事件订阅
- ServBay如何启用并运行Webman项目
- 使用mpdf实现导出pdf文件功能
- Medoo 轻量级PHP数据库框架
- 在PHP中编写和运行单元测试
- 9 PHP运行时基准性能测试
- QR码生成器在PHP中的源代码
- 使用Gogs极易搭建的自助Git服务
- Gitea
- webman如何记录SQL到日志?
- Sentry PHP: 实时监测并处理PHP应用程序中的错误
- Swoole v6 Alpha 版本已发布
- Proxypin
- Rust实现的Redis内存数据库发布
- PHP 8.4.0 Alpha 1 测试版本发布
- 121
- Golang + Vue 开发的开源轻量 Linux 服务器运维管理面板
- 内网穿透 FRP VS Tailscale
- 新一代开源代码托管平台Gitea
- 微服务系列
- Nacos云原生配置中心介绍与使用
- 轻量级的开源高性能事件库libevent
- 国密算法
- 国密算法(商用密码)
- GmSSL 支持国密SM2/SM3/SM4/SM9/SSL 密码工具箱
- GmSSL PHP 使用
- 数据库
- SQLite数据库的Web管理工具
- 阿里巴巴MySQL数据库强制规范
- PHP
- PHP安全测试秘密武器 PHPGGC
- 使用declare(strict_types=1)来获得更健壮的PHP代码
- PHP中的魔术常量
- OSS 直传阿里腾讯示例
- PHP源码编译安装APCu扩展实现数据缓存
- BI性能DuckDB数据管理系统
- 为什么别人可以是架构师!而我却不是?
- 密码还在用 MD5 加盐?不如试试 password_hash
- Elasticsearch 在电商领域的应用与实践
- Cron 定时任务入门
- 如何动态设置定时任务!而不是写死在Linux Crontab
- Elasticsearch的四种查询方式,你知道多少?
- Meilisearch vs Elasticsearch
- OpenSearch vs Elasticsearch
- Emlog 轻量级开源博客及建站系统
- 现代化PHP原生协程引擎 PRipple
- 使用Zephir编写C扩展将PHP源代码编译加密
- 如何将PHP源代码编译加密,同时保证代码能正常的运行
- 为什么选择Zephir给PHP编写动态扩展库?
- 使用 PHP + XlsWriter实现百万级数据导入导出
- Rust编写PHP扩展
- 阿里云盘开放平台对接进行文件同步
- 如何构建自己的PHP静态可执行文件
- IM后端架构
- RESTful设计方法和规范
- PHP编译器BPC 7.3 发布,成功编译ThinkPHP8
- 高性能的配置管理扩展 Yaconf
- PHP实现雪花算法库 Snowflake
- PHP官方现代化核心加密库Sodium
- pie
- 现代化、精简、非阻塞PHP标准库PSL
- PHP泛型和集合
- 手把手教你正确使用 Composer包管理
- JWT双令牌认证实现无感Token自动续期
- 最先进PHP大模型深度学习库TransformersPHP
- PHP如何启用 FFI 扩展
- PHP超集语言PXP
- 低延迟双向实时事件通信 Socket.IO
- PHP OOP中的继承和多态
- 强大的现代PHP高级调试工具Kint
- PHP基金会
- 基于webman+vue3高质量中后台框架SaiAdmin
- 开源免费的定时任务管理系统:Gocron
- 简单强大OCR工具EasyOCR在PHP中使用
- PHP代码抽象语法树工具PHP AST Viewer
- MySQL数据库管理工具PHPMyAdmin
- Rust编写的一款高性能多人代码编辑器Zed
- 超高性能PHP框架Workerman v5.0.0-beta.8 发布
- 高并发系列
- 入门介绍及安装
- Lua脚本开发 Hello World
- 执行流程与阶段详解
- Nginx Lua API 接口开发
- Lua模块开发
- OpenResty 高性能的正式原因
- 记一次查找 lua-resty-mysql 库 insert_id 的 bug
- 包管理工具OPM和LuaRocks使用
- 异步非阻塞HTTP客户端库 lua-resty-http
- Nginx 内置绑定变量
- Redis协程网络库 lua-resty-redis
- 动态HTML渲染库 lua-testy-template
- 单独的
- StackBlitz在线开发环境
- AI
- 基础概念
- 12312
- 基础镜像的坑
- 利用phpy实现 PHP 编写 Vision Transformer (ViT) 模型
- 语义化版本 2.0.0