Linux cron 避坑指南

場景

好多系統中會用到郵件系統,咱們假設有一個 PHP 腳本用來發送郵件。使用 Linux cron 每分鐘執行一次php

咱們暫時不引入隊列系統,其實使用隊列處理此方式更優。shell

咱們獲得下面的基本配置bash

* * * * * php /home/app/email.php
複製代碼

問題分析和解決

若是這個郵件服務出現異常,進程僵死怎麼辦?

假設因爲未知因素, email.php 腳本一直執行,沒有退出。極端的狀況,進入一個 while 死循環。app

這下倒好,原來講好的一分鐘執行一次,如今一直死這邊了,後面的腳本也不能跑了測試


解決辦法:ui

使用 timeout,假設咱們設定每一個腳本最多執行時間位 200秒,超過 200秒 就自動死掉。this

* * * * * timeout 200 php /home/app/email.php
複製代碼

若是這個腳本執行時間超過 60秒,下一分鐘又會執行 php email.php,若是避免重複執行?

這樣會出現,有兩個進程同時在執行 php email.php,那會不會出現同一個任務被執行了兩次?spa


解決辦法:日誌

使用 flock 進行互斥控制code

用法:
 flock [選項] <文件|目錄> <命令> [<參數>...]
 flock [選項] <文件|目錄> -c <命令>
 flock [選項] <文件描述符號碼>

經過 shell 腳本管理文件鎖。

選項:
 -s, --shared             獲取共享鎖
 -x, --exclusive          獲取排他鎖(默認)
 -u, --unlock             移除鎖
 -n, --nonblock           失敗而非等待
 -w, --timeout <秒>       等待限定的時間
 -E, --conflict-exit-code <數字>     衝突或超時後的退出代碼
 -o, --close              運行命令前關閉文件描述符
 -c, --command <命令>      經過 shell 運行單個命令字符串
 -F, --no-fork            執行命令時不 fork
     --verbose            增長詳盡程度

 -h, --help               display this help
 -V, --version            display version
複製代碼

咱們用到其中的排他設置

* * * * * flock -xn /tmp/test.lock -c "timeout 200 php /home/app/email.php"
複製代碼

記錄好日誌

定時任務可能要記錄日誌呀,否則後期怎麼排查

* * * * * flock -xn /tmp/test.lock -c "timeout 200 php /home/app/email.php >> /home/log/test.log 2>&1" 
複製代碼

總結

* * * * * flock -xn /tmp/test.lock -c "timeout 200 php /home/app/email.php >> /home/log/test.log 2>&1" 
複製代碼

番外篇 頻率提高

我以爲一分鐘一次頻率過低,想 10s 執行一次怎麼辦?

* * * * * php /home/app/email.php >> /home/log/test.log 2>&1
* * * * * ( sleep 10 ; php /home/app/email.php >> /home/log/test.log 2>&1 )
* * * * * ( sleep 20 ; php /home/app/email.php >> /home/log/test.log 2>&1 )
* * * * * ( sleep 30 ; php /home/app/email.php >> /home/log/test.log 2>&1 )
* * * * * ( sleep 40 ; php /home/app/email.php >> /home/log/test.log 2>&1 )
* * * * * ( sleep 50 ; php /home/app/email.php >> /home/log/test.log 2>&1 )
複製代碼

番外篇 flock 測試

準備一個 php 腳本 /home/rovast/Code/flock/test.php

<?php

$i = 10000;
while ($i > 0) {
  echo --$i . \PHP_EOL;
  sleep(1);
}
複製代碼

執行

flock -xn /tmp/mytest.lock -c "timeout 30 php /home/rovast/Code/flock/test.php"
複製代碼

咱們看到終端不停輸出數值

9999
9998
9997
9996
9995
9994
9993
9992
9991
9990
複製代碼

咱們再打開另一個終端,執行

flock -xn /tmp/mytest.lock -c "timeout 30 php /home/rovast/Code/flock/test.php"
複製代碼

咱們發現:

  1. 第二次執行的沒有輸出(由於 flock 互斥)
  2. 第一個執行的,30秒後自動關閉進程(由於 timeout 30)
相關文章
相關標籤/搜索