## 概述
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
```

*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作業。
如果這是您第一次使用該命令,系統可能會提示您在繼續之前選擇一個編輯器。

接下來,要添加一個cron作業,只需按照上面解釋的語法向crontab文件添加一個新行。例如,我們將通過添加以下行來安排位于用戶主目錄中的備份腳本`backup.sh`每天在`3:00 AM`運行:
```
0 3 * * * /home/linuxiac/backup.sh
```

以`#`符號為前綴并在文件開頭注釋掉的許多行可以作為設置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
```

*創建系統范圍的Cron作業*
與用戶cron作業不同的是,在最初的五個時間字段之后包含了一個額外的列。此列允許指定將在其下執行作業的用戶帳戶-在本例中為root。
但是,直接編輯`/etc/crontab`文件有兩個主要缺點。首先,這種方法不提供語法檢查,增加了出錯的風險。
第二個原因是`/etc/crontab`會影響整個系統,不正確的輸入可能會產生廣泛的影響,可能會影響系統的穩定性或安全性。所以,小心使用。
### 列出用戶的Cron作業
要確保已正確調度cron作業,可以使用以下命令顯示用戶的crontab文件內容:
```
crontab -l
```

此命令列出為用戶計劃的所有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/
```

### 列出其他用戶的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
```

這將在沒有確認提示的情況下刪除當前用戶的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
```

確保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