2021-05-12 14:32:11
Linux 定時任務 crontab 和 Systemd Timer 詳解
一、說說八卦
?說到定時任務,我們常用的就是 crond 服務,但是我們不知道還有另外一種定時方式,那就是 systemd
,我們常用 systemd
來管理我們的服務,但是我們卻不知道,我們還可以通過 systemd
來設定定時任務。本文將記錄下 crond
服務和 systemd
服務來設定定時任務。 (at 命令使用較少,在此未記錄)
二 、crond服務
我們常用的定時任務就是 crond
服務,crontab
是crond
服務的常用命令,我們經常通過該服務來定時或者周期性幫我們執行一些任務。
crond 服務的一些基本概念
crond 讀取組態檔會從以下幾個路徑讀取:
/var/spool/cron/
, 由crontab -e
進行寫入,組態檔無需指定使用者/etc/crontab
,只能root
進行編輯,組態檔需指定使用者/etc/cron.d/
,在此資料夾下建立定時任務檔案,組態檔需指定使用者
crond 服務的常用檔案:
-
/var/spool/cron/
-
/etc/crontab
-
/etc/cron.d/
-
/var/log/cron
# crond 服務紀錄檔位置 -
/etc/cron.deny
# 禁止使用 crond 服務的賬號,預設建立的使用者是允許使用 crond 服務的。要禁止某個使用者,就直接將該使用者名稱寫入該檔案
crontab 常用命令
# 檢視當前的 crontab 任務
crontab -l
# 編輯 crontab 任務,不符合規則的任務會報錯。
crontab -e
# 幫助其他使用者檢視/編輯 crontab 任務,只有 root 使用者才可以使用。
crontab -u username -l # 檢視
crontab -u username -e # 編輯
# 刪除所有的 crontab 任務
crontab -r
# crond 服務狀態
systemctl status crond
# crond 服務啟動/暫停/重新啟動
systemctl start/stop/reload crond
crontab 定時任務基本語法
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * command to be executed
字元 | 含義 |
---|---|
* | 任何時刻,放在分鐘位置上就表示每分鐘。放在小時位置就表示每小時。 |
, | 分割時段,比如要在3點和6點都執行,就可以寫 3,6 |
- | 表示一個區間,比如要1點到5點的20分都執行任務,20 1-5 * * * command |
/n | n代表的是數位,表示每隔 n 個時間執行一次。 比如要每2分鐘執行任務,*/2 * * * * command |
crontab -e (/var/spool/cron) 設定
crontab -e 命令是會檢查語法的,語法錯誤的話,是會不通過的,crontab -e 儲存在 /var/spool/cron
資料夾下,並且是以建立使用者命名的,比如我們root
使用者建立的定時任務就是儲存在 `/var/spool/cron/root
crontab 使用範例:
以下命令都是通過crontab -e
進行編輯的
-
要在每天23點10分和1點10分對資料庫進行備份,資料庫備份指令碼為
/opt/scripts/back.sh
。10 23,1 * * * /opt/scripts/back.sh
-
要在 0點到6點 每隔2小時 對資料庫進行備份,資料庫備份指令碼為
/opt/scripts/back.sh
0 0-6/2 * * * /opt/scripts/back.sh
/etc/crontab 設定
/etc/crontab
的語法格式和 crontab -e
大致相同,前者需要指定使用者,後者不需要。
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root # 指的就是當有 stdout 和 stderr 時,傳送mail 給誰,預設是root,我們可以指定我們的e-mail賬號,但是前提要在本地設定好郵件傳送賬號
* * * * * user-name command to be executed
#範例:25-32/2 * * * * root /opt/test.sh
/etc/cron.d/ 設定
在 /etc/cron.d/
下建立一個檔案,檔案設定和/etc/crontab
是一樣的,需要指定使用者。
注意點:
在 Linux 底下的 crontab 會自動的幫我們每分鐘重新讀取一次 /etc/crontab 的例行工作事項,但是某些原因或者是其他的 Unix 系統中,由於 crontab 是讀到記憶體當中的,所以在你修改完 /etc/crontab 之後,可能並不會馬上執行, 這個時候請重新啟動 crond 這個服務吧!『systemctl restart crond』
我們在設定計劃任務時需要注意一個問題,就是 如果我們設定了月日,就不要設定星期,這兩者是衝突的,只能同時存在一個。
* 15 * * 1-5 /usr/local/bin/tea_time.sh
該指令碼表示,每週一到週五下午3點,3點的每分鐘執行一次指令碼
/usr/local/bin/tea_time.sh
三 、systemd 服務
之前對於systemd
具有定時任務的功能還是只有耳聞,並沒有實際操作過,今天進行實際操作了下,發現也不錯的。
systemd
實際是通過定義一個timer
單元來建立一個定時任務。它包含了兩大內容,首先定義一個service
單元,這個service
單元定義了我們想定時執行的任務。然後再定義一個timer
單元,通過timer
單元定義定時規則去執行之前的service
單元。
1. 建立定時指令碼
首先我們建立一個指令碼叫做 now_time.sh
,指令碼內容就是輸出當時的時間:
cat <<EOF >/opt/now_time.sh
#!/bin/bash
echo "$(date)" >>/tmp/time_record.log
EOF
chmod 755 /opt/now_time.sh # 注意一定要更改許可權,否則後面會由於沒有執行許可權而報錯
2. 建立 Service
單元
然後需要建立一個 Service單元 timerecord
cat <<EOF >/usr/lib/systemd/system/timerecord.service
[Unit]
Description=now time service
[Service]
ExecStart=/opt/now_time.sh
[Install]
WantedBy=multi-user.target
EOF
然後把 timerecord
作為系統服務。
systemctl start timerecord
3. 建立 Timer
單元
在建立 Timer
單元前,我們需要先了解下如何設定 Timer
,
[Unit] # 定義後設資料
[Timer] #定義定時器
OnActiveSec:定時器生效後,多少時間開始執行任務
OnBootSec:系統啟動後,多少時間開始執行任務
OnStartupSec:Systemd 進程啟動後,多少時間開始執行任務
OnUnitActiveSec:該單元上次執行後,等多少時間再次執行
OnUnitInactiveSec: 定時器上次關閉後多少時間,再次執行
OnCalendar:基於絕對時間,而不是相對時間執行,用於和 crond 類似的定時任務 ,以實際時間執行。
AccuracySec:如果因為各種原因,任務必須推遲執行,推遲的最大秒數,預設是60秒
Unit:真正要執行的任務,預設是同名的帶有.service字尾的單元
Persistent:如果設定了該欄位,即使定時器到時沒有啟動,也會自動執行相應的單元
WakeSystem:如果系統休眠,是否自動喚醒系統
範例:
-
在系統啟動15分鐘後啟動,並在系統執行時,每週啟動一次。
[Unit] Description=Run foo weekly and on boot [Timer] OnBootSec=15min OnUnitActiveSec=1w [Install] WantedBy=timers.target
-
每週執行一次(周一凌晨0點)。啟用後,如果錯過了上次啟動時間,,它會立即觸發服務,例如由於系統斷電:
[Unit] Description=Run foo weekly [Timer] OnCalendar=weekly Persistent=true [Install] WantedBy=timers.target
-
每天周一下午3點10分執行
如果需要具體的時間,我們可以給
OnCalendar
設定具體時間值,形如Year-Month-Day Hour:Minute:Second
[Unit] Description=Run timerecord on Monday 3:10 [Timer] OnCalendar=Mon *-*-* 15:10:00 Unit=timerecord [Install] WantedBy=timers.target
-
每隔5秒執行一次
[Unit] Description=Run timerecord every 5s [Timer] OnUnitActiveSec=5s # 可以設定為 5m,1h Unit=timerecord [Install] WantedBy=timers.target
-
每個小時的每隔10分鐘 進行備份服務
[Unit] Description=backup [Timer] OnCalendar=*-*-* 0/1:0/10:00 Unit=backup [Install] WantedBy=multi-user.target
建立 Timer
單元 record
:每隔1分鐘執行一次
cat <<EOF > /usr/lib/systemd/system/timerecord.timer
[Unit]
Description=Run timerecord every 5s
[Timer]
OnUnitActiveSec=1m # 可以設定為 5m,1h
Unit=timerecord #指定 Service 服務名
[Install]
WantedBy=timers.target
EOF
啟用定時任務
systemctl daemon-reload #重新載入設定
systemctl start timerecord.timer # 啟動定時任務
常用命令:
systemctl start timerecord.timer# 啟動定時任務
systemctl stop timerecord.timer# 暫停定時任務
systemctl status timerecord.timer# 檢視定時任務服務狀態
systemctl restart timerecord.timer# 重新啟動定時任務狀態
systemctl list-timers --all # 檢視定時任務列表
systemctl daemon-reload # 更改了組態檔後,需要重新載入
journalctl -u mytimer.timer # 檢視 mytimer.timer 的紀錄檔
journalctl -u mytimer # 檢視 mytimer.timer 和 mytimer.service 的紀錄檔
journalctl -f # 從結尾開始檢視最新紀錄檔
journalctl -f -u timer.timer # 從結尾開始檢視 mytimer.timer 的紀錄檔
相關文章