 
                
            在 Linux 上週期性執行任務 - Cron
                    
                        2021, Apr 14    
                    
                
            操作 linux 時常會需要一些週期性的任務,例行的資料備份、測試腳本等等,這篇簡介一下 linux 上常用的例行任務工具 Cron
Cron
是一款運行在 Unix like 環境下的週期性任務管理系統,可以基於時間點設定任務的執行,可以設定在特定的時間、日期、間隔之下執行任務
cron 的執行是基於 crontab 的指定格式來運作的,crontab 的文件會被一個 crond 的 daemon 持續監控確認是否需要執行任務,而每一項 crontab 的任務也被稱作 cron job
crond daemon
crond 會週期性的去檢查 crontab 的任務內容是否須被執行,以每分鐘為週期去檢查以下路徑的 crontab
- /etc/crontab: 為系統任務時間表
- /etc/cron.d/: 包含系統層面的任務表,不同用戶間共用
- /var/spool/cron/: 用戶透過 crontab 指令創建的任務表,會依照不同用戶分開
crontab
crontab 指令是用來維護跟查看該用戶的任務表,一般不建議直接去修改任務表因此可以透過 crontab 的指令去操作,crontab 指令編輯的任務表會被存放在 /var/spool/cron/ 路徑下
指令
- crontab -e: 編輯 crontab
- crontab -l: 列出正在套用的 crontab 任務
- crontab -r: 清除所有的 crontab 任務
- crontab <filename>: 套用檔案裡撰寫的 crontab 任務
- crontab -u <user> <command>: 切換不同用戶使用 crontab 指令
語法
- 用戶文件: 也就是透過 crontab -e編輯的內容
# ┌──分鐘(0 - 59)
# │ ┌──小時(0 - 23)
# │ │ ┌──日(1 - 31)
# │ │ │ ┌─月(1 - 12)
# │ │ │ │ ┌─星期(0 - 6 => 周日到周六)
# │ │ │ │ │
# * * * * * 執行的任務
- 系統文件: 被存放在 /etc/crontab或/etc/cron.d/下的文件
# ┌──分鐘(0 - 59)
# │ ┌──小時(0 - 23)
# │ │ ┌──日(1 - 31)
# │ │ │ ┌─月(1 - 12)
# │ │ │ │ ┌─星期(0 - 6 => 周日到周六)
# │ │ │ │ │
# * * * * * 執行用戶 執行的任務
- crontab 的任務執行是在符合時間表達式的條件時去執行任務,例如:
    - 1 * * * *: 每天每小時的 1 分
- 1,3,5,7 * * * *: 每天每小時的 1,3,5,7 分
- 1-7 * * * *: 每天每小時的 1~7 分,每分鐘都會執行
- */3 * * * *: 每天每小時每 3 分鐘執行
 
- 還有一些既定好的參數可以不用自己寫:
    - @reboot: 僅在開機執行一次
- @yearly或- @annually: 等同於- 0 0 1 1 *
- @monthly: 等同於- 0 0 1 * *
- @weekly: 等同於- 0 0 * * 0
- @daily或- @midnight: 等同於- 0 0 * * *
- @hourly: 等同於- 0 * * * *
 
這裡有一個線上的編輯器可以幫助撰寫 crontab 格式文件: crontab.guru
重新啟動服務
設定完 crontab 文件之後,還需要重啟 cron 服務才能真正套用,可以透過以下方式重啟服務:
- /etc/init.d/cron restart
- sudo service cron restart
- sudo systemctl restart cron
Cron Log
為了確認 crontab 有被正常運作可以透過一些方式來確認:
- grep CRON /var/log/syslog: 直接查看相關的 syslog
- * * * * * command >> /cron.log 2>&1: 透過 stdout 直接輸出訊息到指定檔案
- 查看 /var/mail/{user}: 預設 crontab 會把結果發送 mail 給用戶
其他
Mail 通知
crontab 預設會將輸出 mail 給使用者,也可以透過設定送出給其他人,也可以設定空字串表示不發送
# 輸出送給 root
MAILTO=root
* * * * * echo "Hello"
執行的 shell 環境
SHELL=/bin/sh
* * * * * echo "Hello"
指定環境變數
有時候需要執行一些程式需要事先設定環境變數,例如執行 node.js
PATH=/bin:/usr/bin:/usr/local/bin
* * * * * node /test.js
權限設定
可能由於一些安全性的考量,會希望只有特定的使用者可以使用 crontab,可以透過設定以下檔案來達到功效
- /etc/cron.allow: 如果存在此檔案,列在之中的帳號才能使用 crontab
- /etc/cron.deny: 如果存在此檔案,列在之中的帳號則都不能使用 crontab
- 如果兩個檔案都不存在,則只有 root 可以使用 crontab