使用 Rust 執行 Cron 作業

banq發表於2024-04-05

什麼是 Cron 作業?
Cron 作業是計劃定期執行的自動化任務。它們經常用於多種任務,包括備份、資料庫更新、電子郵件傳送等等,並且不需要每次都由專人啟動。

cron 作業的核心是 cron 守護程序。將其視為一個幕後工作人員,不斷檢查一個特殊列表(稱為 cron 表或 crontab),以檢視需要完成哪些任務以及何時完成。列表中的每個任務都包含一個唯一的計劃(一個 cron 表示式),指示守護程式何時執行它,然後是要採取的特定操作。

cron 的工作方式非常簡單,但也很聰明。每分鐘,該工作人員都會檢查列表以查詢當前時間安排的任何任務。如果找到任何任務,它會立即在單獨的程序中啟動這些任務。這種設定可確保任務準確地按預期發生,無論是每天的特定時間,還是更不尋常的模式,例如僅在特定日期或月份。

Cron 語法
cron 模式是使用 cron 作業配置自動化操作的一個重要方面。它經過巧妙設計,可讓您幾乎在您能想到的任何時間安排任務,從每一分鐘到特定日期或月份的精確時間。該模式包含六個欄位,每個欄位由空格分隔,每個欄位代表一個不同的時間單位。

  * * * * * *
  | | | | | |
  | | | | | └─── day of week (0 - 7) (Sunday to Saturday; 7 is also Sunday)
  | | | | └───── month (1 - 12)
  | | | └─────── day of month (1 - 31)
  | | └───────── hour (0 - 23)
  | └─────────── minute (0 - 59)
  └───────────── second (optional, 0 - 59)


在 Rust 中實現 Cron 作業
Rust 生態系統擁有豐富的用於各種任務的庫,包括排程 cron 作業。其中,由於多種原因, cron crate脫穎而出成為最合適的選擇。它易於整合,文件齊全,並且不斷更新,使其比其他庫更可靠。

首先,透過在終端中執行以下命令來建立一個新的 Rust 專案。

cargo new rust_cron_job
cd rust_cron_job

這些命令rust_cron_job在同名的新目錄中建立一個新的 Rust 專案,其中包含基本的Rust 二進位制專案結構。

接下來,將 cron 庫新增到您的專案中,方法是將其包含在Cargo.toml檔案的以下[dependencies]部分中:

[dependencies]
cron = <font>"0.12.1"
chrono =
"0.4" 

此步驟通知 Cargo 您的專案依賴於 cron 和 chronocrates;後者是在 Rust 中處理日期和時間的先決條件。

現在您已經設定了 Rust 專案並宣告瞭必要的依賴項,您可以開始編寫您的第一個 cron 作業。編輯 專案 src目錄中的main.rs檔案以包含以下 Rust 程式碼:


use chrono::Utc;
use cron::Schedule;
use std::str::FromStr;
use std::thread;

fn main() {
    let expression = <font>"0/5 * * * * *";
    let schedule = Schedule::from_str(expression).expect(
"Failed to parse CRON expression");

    for datetime in schedule.upcoming(Utc).take(1) {
        let now = Utc::now();
        let until = datetime - now;
        thread::sleep(until.to_std().unwrap());
        println!(
"Hello, world!");
    }
}

在此示例中,任務設定為按照 cron 表示式 的定義每五秒執行一次"0/5 * * * * *"。該程式碼將此表示式轉換為時間表,並計算下一次執行之前的確切時間。然後,它會使用 , 暫停執行thread::sleep(),直到達到該時間,以確保精確計時。一旦等待結束,它就會執行任務,在本例中列印“ Hello, world! ”。

透過在終端中執行以下命令來執行 cron 作業:

cargo run
此命令編譯並執行您的 Rust 應用程式,您應該看到“Hello, World!”執行程式碼五秒後列印到您的終端,展示了 cron 作業的執行情況。

但是,重要的是要了解該任務不會繼續每五秒執行一次,而是在第一次執行後停止。這種行為是由於 Rust 的設計造成的,與 JavaScript 等語言不同,Rust 不包含內在的事件迴圈。 Rust 需要顯式管理連續任務執行或迴圈。對於在 Rust 應用程式的單次執行中定期重複的任務,您必須顯式實現迴圈邏輯。

為了修改我們的示例以實現連續執行,我們可以引入一個迴圈,該迴圈不斷檢查下一個計劃時間並相應地執行任務。使用以下程式碼 更新 src/main.rs以實現此目的。

use chrono::{Local, Utc};
use cron::Schedule;
use std::str::FromStr;
use std::thread;

fn main() {
    let expression = <font>"0/5 * * * * *";
    let schedule = Schedule::from_str(expression).expect(
"Failed to parse CRON expression");

    loop {
        let now = Utc::now();
        if let Some(next) = schedule.upcoming(Utc).take(1).next() {
            let until_next = next - now;
            thread::sleep(until_next.to_std().unwrap());
            println!(
               
"Running every 5 seconds. Current time: {}",
                Local::now().format(
"%Y-%m-%d %H:%M:%S")
            );
        }
    }
}

在此連續版本中,應用程式保持活動狀態,進入一個迴圈,頻繁檢查計劃以檢視是否到了再次執行任務的時間。如果是這樣,應用程式將休眠直到下一個執行時間,然後列印當前時間,演示任務每 5 秒執行一次,如下所示。


Running every 5 seconds. Current time: 2024-03-12 18:22:35
Running every 5 seconds. Current time: 2024-03-12 18:22:40
Running every 5 seconds. Current time: 2024-03-12 18:22:45
Running every 5 seconds. Current time: 2024-03-12 18:22:50
Running every 5 seconds. Current time: 2024-03-12 18:22:55
Running every 5 seconds. Current time: 2024-03-12 18:23:00
Running every 5 seconds. Current time: 2024-03-12 18:23:05
Running every 5 seconds. Current time: 2024-03-12 18:23:10
...

 

相關文章