Linux排程上一輪還沒跑完?用flock避免工作重疊

匯入資料每分鐘啟動一次,但某一輪花了兩分鐘,下一輪又開始寫同一批檔案。排程準時啟動,不代表上一輪已經結束。若工作不能重疊,可以用Linux的flock把同一項工作包起來:只有拿到鎖的那一輪才執行。

先決定第二輪應該等待,還是跳過。flock預設會等鎖;加上-n則立即回報沒拿到,不會替你排隊補跑。這是工作流程的選擇,不能把「沒有執行」當成「已完成」。

先在兩個終端看見同一把鎖

在自己的Linux測試環境執行下面這行,它會建立一個獨立暫存目錄,並印出路徑。把實際印出的路徑複製給兩個終端的demo_dir;兩邊必須指向同一個目錄,別各自再跑一次mktemp。

mktemp -d /tmp/flock-demo.XXXXXX

先在終端A啟動一個只等待10秒的虛構工作。把路徑換成剛才的實際結果,不要使用別人的鎖檔,也不要拿正式匯入工作來試。

demo_dir=/tmp/flock-demo.實際結果
flock -n -E 75 "$demo_dir/job.lock" \
  bash -c 'printf "A started\n"; sleep 10; printf "A finished\n"'

看到A started後,在10秒內從終端B執行:

demo_dir=/tmp/flock-demo.實際結果
if flock -n -E 75 "$demo_dir/job.lock" \
  bash -c 'printf "B started\n"'; then
  printf 'B completed\n'
else
  rc=$?
  printf 'B did not succeed, exit=%s\n' "$rc"
fi

A仍持鎖時,B不會印出B started,會得到退出碼75。等A finished出現後,再跑同一段B,這次才會印出B started與B completed。鎖檔還在不影響重跑;檔案存在與鎖正在被持有是兩件事。

把沒拿到鎖和工作失敗分開記錄

-E 75指定的是鎖衝突的退出碼。若已拿到鎖且成功啟動子命令,flock會傳回子命令的退出碼。因此退出碼75也可能是你的工作自己回傳的75;不能只看這個數字,就斷言另一輪正在執行。

套到真實工作前,核對工作本身的返回值規則。若約定保留75給鎖衝突,工作就不應用同一個值表示其他失敗;若無法約定,紀錄還要能分辨是否已進入工作。工作返回非零時要保留原因,別用|| true讓呼叫者一律看見成功。

下面刻意讓拿到鎖的工作退出7。請在A結束後單獨執行,結果應是7,並非75:

demo_dir=/tmp/flock-demo.實際結果
if flock -n -E 75 "$demo_dir/job.lock" bash -c 'exit 7'; then
  printf 'work succeeded\n'
else
  rc=$?
  printf 'work failed, exit=%s\n' "$rc"
fi

失敗分支第一行立即保存$?,避免後面的printf把狀態改掉。若用if ! flock ...再讀取$?,看到的是反轉後的條件結果,無法原樣取得這次退出碼。

不要刪鎖檔來強行開下一輪

flock使用的是檔案鎖,不是靠檔案內容寫著busy來決定。鎖通常在持有它的檔案描述符關閉時釋放。工作執行中刪除鎖檔再建立同名檔案,可能讓下一輪鎖到另一個檔案,破壞原本的互斥關係。

示例的sleep結束後自然釋鎖,不需要刪檔。正式工作也應保留穩定且由該工作帳號可存取的鎖路徑,不要每輪生成不同的鎖名。手動啟動、排程啟動與其他入口都要使用同一套鎖法;繞過flock直接執行工作,仍可能同時修改資料。

包住的命令若啟動背景程序,檔案描述符的繼承可能延長持鎖時間,或使外層命令結束與真正工作結束不一致。先讓被包住的工作在前景完成,再驗證自己的程序結構;不要因為終端已返回,就認定所有子工作都已結束。

選擇等待上限,再接回排程

若不能跳過一輪,可用-w 5 -E 75最多等5秒;時間到仍拿不到鎖就回報75。不要同時加-n,先選清楚等待或立即退出。省略這兩種選項時預設等待,上一輪長時間不結束,就可能讓後續啟動一直等。

先用兩個測試終端核對立即退出、等待逾時、釋鎖後成功與工作本身失敗四種分支,再把已確認的命令放回自己的排程。示例的10秒、5秒只是方便觀察,不是備份或匯入工作的建議上限;實際上限取決於工作耗時與資料新鮮度要求。

這是同一鎖機制下的互斥,不是資料庫交易、分散式鎖或完成保證。多台機器各自使用本機鎖檔,不能互相協調;NFS、CIFS等檔案系統也有實作及掛載限制。跨主機工作需另外設計協調方式,不能只把路徑放到共用目錄就宣稱已安全。

參考資料

原文鏈接:https://wntheme.com/linux-flock-scheduled-job-overlap/,轉載請註明出處。
0

評論0

顯示驗證碼
沒有帳號?註冊  忘記密碼?