flock
Sun 16 February 2025တခါတခါ ကိုယ့်အကြောင်း ပြန်စဉ်းစားမိရင် အလုပ်သဘောအရ Programmer ဆိုတာ ဘယ်သူမှ မငြင်းကြပေမယ့် တကယ် Develop လုပ်ရမယ်ဆို အင်မတန်မှ ပျင်းတဲ့လူရယ် လက်ကြောမတင်းဘူး ပြောရမယ်ထင်တယ်။ Unix philosophy ဖြစ်တဲ့ Make each program do one thing well. Expect the output of every program to become the input to another, as yet unknown, program.
ဆိုတာကို အမြဲအကာကွယ်ယူပြီး Tools သေးသေးလေးတွေကို ကပ်သပ်ပြီး သုံးလေ့ရှိတယ်။ မှတ်မှတ်ရရ NTU မှာနေတုံးက ကျောင်းပိတ်ရက် အလုပ်လုပ်တော့ ETL တခု လုပ်ပေးဖို့ရှိတာ ဘာမှမသုံးပဲ Bash နဲ့ရေးပြီး Windows ဖြစ်နေလို့ Cygwin နဲ့ Run ထားခဲ့ဖူးတယ်။
အခုအလုပ်ထဲမှာ တချို့ System တွေက Bash script တွေနဲ့ အချိန်အလိုက် Run ပြီးတော့ အလုပ်လုပ်နေတာ အတော်များများရှိတယ်။ နှစ်ပေါင်းများစွာ လူအမျိုးမျိုး ရေးသွားတော့ Style အမျိုးမျိုးနဲ့ပေါ့ ဖတ်ကြည့်နေရင်း Style တခုပြောင်းသွားရင် လူတယောက် ပြောင်းသွားပြီပဲ။ တချို့ Scripts တွေက အချိန်တခုထဲမှာ Instance တခုထက်ပိုပြီး Run မယ်ဆိုရင် ပြဿနာရှိတော့ တကြိမ်မှာတခါထက်ပိုပြီး အလုပ်မလုပ်အောင်လို့ ထိမ်းထားတာရတွေရှိတယ်။
လက်ရှိ Code အများစုက Lock file တခုထဲမှာ Process ID ကို ရေးထားလိုက်ပြီး နောက်တခု Run မိတယ်ဆိုရင် Lock file ထဲက Process ပြီးမပြီးကြည့်ပြီး အလုပ်လုပ်မယ် မလုပ်ဘူးဆုံးဖြတ် အားလုံးပြီးသွားရင် Lock file ကို ရှင်းထားခဲ့ဆိုတာမျိုးနဲ့ ရေးထားကြတာ။ မှားတယ် မဟုတ်ပေမယ့် တချို့ Script တွေမှာကျ အရင်ရှိတဲ့ Process ID ရှိမရှိမစစ်ပဲ Lock file ရှိမရှိပဲ စစ်ထားတဲ့ဟာမျိုးကျ Script တခုလုံး မပြီးလိုက်ပဲ မထင်မှတ်တဲ့ ပြဿနာဝင်လာရင်တို့ System reboot ဖြစ်သွားတာတို့ Process ကို Kill လုပ်လိုက်မိတာတို့နဲ့ဆို Lock file မရှင်းခဲ့ပဲ ကျန်နေခဲ့ပြီး လက်နဲ့လိုက်ပြီး ရှင်းပေးရတာ ရှိတတ်တယ်။
အရင်ကသူများ ဒုက္ခဆိုပေမယ့် ကိုယ့်လက်ထဲ ရောက်လာတော့ Manual လိုက်ရှင်းရတာတွေ ကိုယ့်ပြဿနာ ကိုယ့်ဒုက္ခဖြစ်လာတော့ ပြင်ရေးဖို့လိုလာတယ်။ ပြင်မယ်ဆိုတော့ အားလုံးအတွက် အရင် Run နေတဲ့ Process ID ပြန်စစ်မလားဆိုတာ လိုက်ထည့်မလားရယ် တခြားကောင်းတဲ့ နည်းလမ်းများ ရှိမလားရယ် ၂ မျိုးစဉ်းစားရတယ်။ ကိုယ့်လိုပြဿနာ တခြားလူတွေလည်း ဖြစ်ကြမှာပဲ လိုက်ရှာကြည့်တော့ Process ID ကို ပြန်စစ်တဲ့နည်းရယ် File system lock ကို သုံးတဲ့နည်းရယ် ၂ မျိုးတွေ့တယ်။ ကိုယ့်အမြင်မှာ File system lock က OS က တာဝန်ယူထားတာဖြစ်လို့ ပိုအဆင်ပြေတာရယ် ပိုလည်းရှင်းတယ်လို့မြင်လို့ File system lock ကို ပြောင်းဖို့ပဲ လုပ်လိုက်တယ်။
File lock လုပ်ဖို့အတွက် flock
ဆိုတဲ့ command တခုပဲလိုတယ် ဒါကလည်း Linux တိုင်းမှာပါတယ်လို့ ပြောလို့ရတဲ့အတွက် ဖြစ်နိုင်သ၍ built-in tools ပဲ သုံးကြဆိုတဲ့ ကိုယ့်ရုံးရဲ့ Security team က လူတွေနဲ့လည်း အတိုက်အခံတွေ လုပ်စရာမလိုဘူးပေါ့။ flock
command သုံးတဲ့အခါ lock လုပ်ချင်တဲ့ file or directory တခုရယ် ကိုယ်လိုအပ်တဲ့ lock type အနေနဲ့ read or exclusive ရယ် lock လုပ်လို့ရရင် run ချင်တဲ့ command ရယ် ပေးလိုက်ရတယ်။ အလုပ်လုပ်ပုံက ရှုပ်ရှုပ်ထွေးထွေးမရှိဘူး ပေးလိုက်တဲ့ file or directory ကို lock လုပ်လို့ရရင် ပေးလိုက်တဲ့ command ကို run ပေးမယ်တဲ့ ပြီးသွားရင်တော့ unlock ပြန်လုပ်ပေးမယ်။ အသေးစိတ်ကတော့ lock လုပ်လို့မရရင် ရတဲ့အထိ စောင့်နေမှာလား အချိန်အတိုင်းအတာတခုထိ စောင့်မလား မစောင့်ပဲနဲ့ ထွက်သွားမှာလား စသည်ဖြင့်တွေ ရှိသေးတာပေါ့လေ။
Terminal 1
flock /tmp/flock_test.txt -c "echo hello>/tmp/flock_test.txt; cat /tmp/flock_test.txt; sleep 60;"
Terminal 2
flock /tmp/flock_test.txt -c "cat /tmp/flock_test.txt;"
စမ်းကြည့်မယ်ဆိုရင် Terminal 1 အတွက် ပေးထားတဲ့ command ကို စမ်းပြီးတော့ run ကြည့်လို့ရတယ်။ ရှုပ်ရှုပ်ထွေးထွေး မဟုတ်ပါဘူး flock
နဲ့ /tmp/flock_test.txt
ကို lock လုပ်လိုက်တယ် ပြီးရင်တော့ file ကို ရေးလိုက်တယ် ပြန်ပြီးတော့ std out မှာ cat
နဲ့ပြန်ထုတ်ပြီး စက္ကန့် ၆၀ စောင့်နေလိုက်တယ်။ အဲဒီ့အချိန်မှာ Terminal 2 အတွက် command ကို run ကြည့်ရင် lock ယူလို့မရတဲ့အတွက် ဆက်မသွားဘူး စောင့်နေလိမ့်မယ် Terminal 1 ဘက်က စက္ကန့် ၆၀ ပြီးသွားတဲ့အချိန်မှ ဆက်ပြီးတော့ အလုပ်လုပ်လိမ့်မယ်။ lock ဖြစ်နေတဲ့ file တွေကို သိချင်ရင် lslocks
command နဲ့ကြည့်ရင် တွေ့ပါလိမ့်မယ်။
flock
နဲ့ အခုခေတ်တော့ ဘယ်သူမှလည်း script တွေနဲ့ ရေးတာဖတ်တာ မလုပ်ကြတော့ အသုံးလည်း သိပ်မရှိတော့တာ။ Bash script တွေကို Multiple instance အလုပ်မလုပ်စေချင်တဲ့ နေရာဘက်ကို ဘယ်လိုသုံးလို့ရမလဲ ပြန်ဆက်ရမယ်ဆိုရင် flock
ရဲ့ man page ကို သွားကြည့်လိုက်ရင် script တွေကို ၁ ခါထက်ပိုပြီး အလုပ်မလုပ်စေချင်ရင် သုံးလို့ရတယ်ဆိုတဲ့ Example တခုကို တွေ့ပါလိမ့်မယ်။ ရှင်းပြရမယ်ဆိုရင် run မယ့် script file ကို lock လုပ်ကြည့်လိုက်တယ် လုပ်လို့ရင် env တခုထဲ ထည့်ထားလိုက်တယ် အဲဒါအပေါ် မူတည်ပြီးတော့ lock လုပ်ထားတာ ရှိတယ်ဆိုရင် ဆက်ပြီးတော့ အလုပ်မလုပ်တော့ဘူး။ ၁ ခါထက်ပိုပြီးတော့ run လို့မရစေချင်တဲ့ script တွေရဲ့ အပေါ်ဆုံးမှာ အဲဒါထည့်ထားရင် အဆင်ပြေပါတယ်။
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -n "$0" "$0" "$@" || :
ကိုယ့်အတွက်က အပေါ်မှာပြထားတဲ့ နည်းလမ်းက တချို့တဝက်အတွက်ပဲ အဆင်ပြေပါတယ်။ တချို့ Script တွေက parameters တွေအပေါ် မူတည်ပါတယ် parameters တွေ မတူဘူးဆိုရင် run လို့ရရမယ်ဆိုတာမျိုးကျ script file ကို lock လုပ်ကြည့်ပြီး ဆုံးဖြတ်လို့မရနိုင်တော့ parameter အပေါ်မူတည်ပြီး lock file မတူညီတာတွေနဲ့ ဆုံးဖြတ်ဖို့လိုပါတယ်။ အဲဒါအတွက်လည်း man page ထဲမှာ နောက်ထပ် Example တခုပါတယ် အဲဒါကို အခြေခံပြီး လိုချင်သလို ပြောင်းရေးလို့ရတယ်။ ကိုယ်သုံးချင်တဲ့ parameters အလိုက် lock file name ကို ပြောင်းတဲ့ code တွေတော့ ထည့်ပေးဖို့လိုမှာပေါ့။
LOCKFILE="/tmp/mylockfile"
(
flock -n 8 || exit 1
# commands executed under lock ...
# ...
) 8 > $LOCKFILE
တကယ်တမ်း ပြောင်းရေးတဲ့အခါတော့ script တွေက အများကြီးတွေဆိုတော့ ပြောသလောက်တော့ မလွယ်ဘူးပေါ့လေ လိုအပ်သလိုတော့ ပြောင်းရေးရတာပေါ့။ Script အတော်များများ ပြင်ရေးပြီးတဲ့အချိန်မှာတော့ System failure ဖြစ်သွားလည်း အရင်လို lock file တွေကို လိုက်ရှင်းရတာတွေ မရှိသလောက် ဖြစ်လာတဲ့အချိန်မှာ ကိုယ်လည်းအတော် သက်သာသွားတယ်။