利用lock檔避免程式重複執行

  想直接看lock應用的腳本範例,可以略過第一個範例。

理解鎖檔概念

#!/bin/sh LOCK_FILE=/var/lock/my.lock if [ -f $LOCK_FILE ]; then echo "$0 is running!" >&2 exit 0 fi touch $LOCK_FILE # Start to do my job. sleep 10 echo "Done." rm -f $LOCK_FILE   在無人使用腳本的情況下,開始時新增檔案my.lock,結束時會刪除檔案my.lock;當腳本正在執行中,若重複執行,就會因my.lock檔案存在,而直接結束程式。

使用trap指令

  若在執行上方範例,在延遲10秒內,輸入Ctrl + C中斷程式,會發生什麼事呢?因為沒執行到最後一行的刪除my.lock動作,my.lock會一直存在,腳本被鎖住,不能再次執行。為避免程式不正常中斷,而被鎖住的問題,可利用trap指令來執行砍檔。 #!/bin/sh LOCK_FILE=/var/lock/my.lock if [ -f $LOCK_FILE ]; then echo "$0 is running!" >&2 exit 0 fi trap "rm -f $LOCK_FILE" EXIT touch $LOCK_FILE # Start to do my job. sleep 10 echo "Done."   無論何種因素結束程式,當程式結束之前,會發送EXIT訊號,trap攔到EXIT後訊號,就會將my.lock砍掉。這樣做,就能避免程式結束,而my.lock還存在的窘境。

嘗試寫檔取代touch

  有沒有一種方法,my.lock不存在時新增,my.lock存在時報錯?利用寫檔的指令能辦到,只要先設定不能覆寫檔案,有檔案存在時,寫檔就會出錯,再判斷出錯跳出程式,就能避免重複執行。
寫一個空檔案的指令為 echo "" >$LOCK_FILE 或者簡化成 echo >$LOCK_FILE 甚至簡化到連echo指令都不呼叫 >$LOCK_FILE 前面再加上不能覆寫的環境設定set -C 當檔案存在時,執行會出現錯誤 $ set -C $ >$LOCK_FILE $ echo $? 0 $ >$LOCK_FILE bash: $LOCK_FILE: cannot overwrite existing file $ echo $? 1 若不希望顯示錯誤訊息 $ set -C $ 2>/dev/null >$LOCK_FILE $ echo $? 0 $ 2>/dev/null >$LOCK_FILE $ echo $? 1   注意2>/dev/null的位置,因為>$LOCK_FILE已經有錯誤輸出了,若後面才設定錯誤輸出導向,就來不及了,錯誤訊息一樣會顯示。想進一步了解輸出導向,可參考「介紹輸出重新導向」。
  但用此方法,若主程式想允許輸出導向可以覆寫,記得加上set +C調整回來。 #!/bin/sh set -C LOCK_FILE=/var/lock/my.lock if ! 2>/dev/null >$LOCK_FILE; then echo "$0 is running!" >&2 exit 0 fi trap "rm -f $LOCK_FILE" EXIT set +C # Start to do my job. sleep 10 echo "Done."   如果喜歡,可以將與鎖檔相關的程式碼擠在一起 #!/bin/sh LOCK_FILE=/var/lock/my.lock if { set -C; 2>/dev/null >$LOCK_FILE; }; then trap "rm -f $LOCK_FILE" EXIT set +C else echo "$0 is running!" >&2 exit 0 fi # Start to do my job. sleep 10 echo "Done."

參考資料

留言

這個網誌中的熱門文章

Python的10進制與16進制轉換

設定CPU的Cache模式:MTRR

ls -l 顯示出現亂碼