উত্তর:
এখানে এমন একটি বাস্তবায়ন রয়েছে যা একটি লকফিল ব্যবহার করে এবং এতে একটি পিআইডি প্রতিধ্বনি করে। পিডফিল অপসারণের আগে প্রক্রিয়াটি মারা গেলে এটি সুরক্ষা হিসাবে কাজ করে :
LOCKFILE=/tmp/lock.txt
if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then
echo "already running"
exit
fi
# make sure the lockfile is removed when we exit and then claim it
trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT
echo $$ > ${LOCKFILE}
# do stuff
sleep 1000
rm -f ${LOCKFILE}
এখানে কৌতুকটি হ'ল kill -0
যা কোনও সিগন্যাল সরবরাহ করে না তবে প্রদত্ত পিআইডি সহ কোনও প্রক্রিয়া বিদ্যমান কিনা তা পরীক্ষা করে দেখুন। এছাড়াও কলটি trap
নিশ্চিত করবে যে আপনার প্রক্রিয়াটি মারা গেলেও (ব্যতীত ) লকফিলটি সরানো হয়েছে kill -9
।
flock(1)
একটি ফাইল স্ক্রিপ্ট লক একটি ফাইল বর্ণনাকারী করতে ব্যবহার করুন । এইভাবে আপনি এমনকি স্ক্রিপ্টের বিভিন্ন অংশ সিঙ্ক্রোনাইজ করতে পারেন।
#!/bin/bash
(
# Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
flock -x -w 10 200 || exit 1
# Do stuff
) 200>/var/lock/.myscript.exclusivelock
এটি সেই কোডটি নিশ্চিত করে (
এবং )
একসাথে কেবল একটি প্রক্রিয়া দ্বারা চালিত হয় এবং প্রক্রিয়াটি কোনও লকের জন্য খুব বেশি সময় অপেক্ষা করে না।
কেভেট: এই বিশেষ আদেশটি একটি অংশ util-linux
। আপনি যদি লিনাক্স ব্যতীত অপারেটিং সিস্টেম চালনা করেন তবে এটি উপলভ্য বা নাও থাকতে পারে।
( command A ) command B
জন্য একটি সাবশেল আহ্বান জানানো হয়েছে command A
। Tldp.org/LDP/abs/html/subshells.html এ নথিভুক্ত ।
if flock -x -w 10 200; then ...Do stuff...; else echo "Failed to lock file" 1>&2; fi
যাতে সময়সীমাটি ঘটে (অন্য কোনও প্রক্রিয়াতে ফাইলটি লক হয়ে আছে), এই স্ক্রিপ্টটি এগিয়ে যায় না এবং ফাইলটি সংশোধন করে না। সম্ভবত ... পাল্টা যুক্তিটি 'তবে এটি যদি 10 সেকেন্ড সময় নেয় এবং লকটি এখনও পাওয়া না যায় তবে এটি কখনই উপলভ্য হবে না' সম্ভবতঃ কারণ লকটি ধরে রাখার প্রক্রিয়াটি শেষ হচ্ছে না (সম্ভবত এটি চালিত হচ্ছে) একটি ডিবাগার অধীনে?)।
exit
ভিতরে থেকে অংশটি (
)
। সাবপ্রসেসটি শেষ হয়ে গেলে, লকটি স্বয়ংক্রিয়ভাবে মুক্তি পায়, কারণ এটি ধারণ করার কোনও প্রক্রিয়া নেই।
"লক ফাইল" এর অস্তিত্ব পরীক্ষা করে এমন সমস্ত পদ্ধতির ত্রুটি রয়েছে।
কেন? কারণ কোনও ফাইল উপস্থিত রয়েছে কিনা তা যাচাই করে দেখার জন্য এবং একক পারমাণবিক ক্রিয়ায় এটি তৈরি করার কোনও উপায় নেই। এর জন্য; সেখানে একটি জাতি এই শর্তে যে হয় হবে পারস্পরিক বর্জনের বিরতি আপনার প্রচেষ্টা করা।
পরিবর্তে, আপনি ব্যবহার করা প্রয়োজন mkdir
। mkdir
এটি এখনও উপস্থিত না থাকলে একটি ডিরেক্টরি তৈরি করে এবং যদি এটি হয় তবে এটি একটি প্রস্থান কোড নির্ধারণ করে। আরও গুরুত্বপূর্ণ বিষয়, এটি এই একক পারমাণবিক ক্রিয়ায় এটি করে যা এই দৃশ্যের জন্য নিখুঁত করে তোলে।
if ! mkdir /tmp/myscript.lock 2>/dev/null; then
echo "Myscript is already running." >&2
exit 1
fi
সমস্ত বিবরণের জন্য, দুর্দান্ত বাশফাক দেখুন: http://mywiki.wooledge.org/BashFAQ/045
আপনি যদি বাসি তালার যত্ন নিতে চান তবে ফুসার (1) ব্যবহারের সুযোগ আসে। এখানে কেবলমাত্র প্রতিকূলতাটি হ'ল অপারেশনটি প্রায় এক সেকেন্ড সময় নেয় তাই এটি তাত্ক্ষণিকভাবে নয়।
এখানে আমি একটি ফাংশন লিখেছি যা একবার ফুয়েজার ব্যবহার করে সমস্যার সমাধান করে:
# mutex file
#
# Open a mutual exclusion lock on the file, unless another process already owns one.
#
# If the file is already locked by another process, the operation fails.
# This function defines a lock on a file as having a file descriptor open to the file.
# This function uses FD 9 to open a lock on the file. To release the lock, close FD 9:
# exec 9>&-
#
mutex() {
local file=$1 pid pids
exec 9>>"$file"
{ pids=$(fuser -f "$file"); } 2>&- 9>&-
for pid in $pids; do
[[ $pid = $$ ]] && continue
exec 9>&-
return 1 # Locked by a pid.
done
}
আপনি এটির মতো স্ক্রিপ্টে এটি ব্যবহার করতে পারেন:
mutex /var/run/myscript.lock || { echo "Already running." >&2; exit 1; }
আপনি যদি বহনযোগ্যতার বিষয়ে চিন্তা না করেন (এই সমাধানগুলি কোনও ইউনিক্স বাক্সে কার্যকরভাবে কাজ করা উচিত), লিনাক্সের ফিউজার (1) কিছু অতিরিক্ত বিকল্প সরবরাহ করে এবং সেখানে ঝাঁক (1) রয়েছে ।
if ! mkdir
লকডিরের ভিতরে থাকা পিআইডি (সসেসফুল স্টার্টআপে) প্রক্রিয়াটি আসলে চলমান এবং স্ট্যালিন সুরক্ষার জন্য স্ক্রিপ্টের অনুরূপ কিনা তা পরীক্ষা করে আপনি অংশটি একত্রিত করতে পারেন । এটি পুনরায় বুটের পরে পিআইডি পুনরায় ব্যবহার করা থেকে রক্ষা করবে এবং এমনকি প্রয়োজন নেই fuser
।
mkdir
এটি পারমাণবিক ক্রিয়াকলাপ হিসাবে সংজ্ঞায়িত হয়নি এবং যেমন "পার্শ্ব-প্রতিক্রিয়া" ফাইল সিস্টেমের একটি বাস্তবায়ন বিশদ। আমি তাকে পুরোপুরি বিশ্বাস করি যদি তিনি বলেন যে এনএফএস এটি পারমাণবিক পদ্ধতিতে প্রয়োগ করে না। যদিও আমি সন্দেহ করি না যে এটি আপনার /tmp
কোনও এনএফএস শেয়ার হবে এবং সম্ভবত এটি কোনও এফএস দ্বারা সরবরাহ করা হবে যা mkdir
পরমাণুভাবে প্রয়োগ করে ।
ln
তৈরি করার জন্য : অন্য ফাইল থেকে একটি হার্ড লিঙ্ক তৈরি করতে ব্যবহার করে । আপনার যদি অদ্ভুত ফাইল সিস্টেম থাকে যা এর গ্যারান্টি দেয় না তবে আপনি নতুন ফাইলের ইনোডটি পরে পরীক্ষা করতে পারেন এটি আসল ফাইলের মতো কিনা।
open(... O_CREAT|O_EXCL)
। এটি করার জন্য আপনার কেবল একটি উপযুক্ত ব্যবহারকারী প্রোগ্রাম প্রয়োজন, যেমন lockfile-create
(ইন lockfile-progs
) বা dotlockfile
(ইন liblockfile-bin
)। এবং নিশ্চিত হয়ে নিন যে আপনি সঠিকভাবে পরিষ্কার করেছেন (উদাঃ trap EXIT
), বা বাসি লকগুলির পরীক্ষা করুন (উদাহরণস্বরূপ --use-pid
)।
ঝাঁক (২) সিস্টেম কলের চারপাশে একটি মোড়কের কল রয়েছে, কল্পনাতীতভাবে, ঝাঁক (1)। এটি ক্লিনআপ ইত্যাদির চিন্তা না করেই নির্ভরযোগ্যভাবে একচেটিয়া লকগুলি অর্জন করা তুলনামূলকভাবে সহজ করে তোলে শেল স্ক্রিপ্টে এটি কীভাবে ব্যবহার করা যায় সে সম্পর্কে ম্যান পৃষ্ঠায় উদাহরণ রয়েছে ।
flock()
সিস্টেম কল POSIX নয় এবং NFS মাউন্ট উপর ফাইলের জন্য কাজ করে না।
flock -x -n %lock file% -c "%command%"
নিশ্চিত হয়েছি যে কেবলমাত্র একটি উদাহরণ কার্যকর হচ্ছে।
আপনার পালের মতো পারমাণবিক অপারেশন প্রয়োজন, অন্যথায় এটি ব্যর্থ হবে।
তবে পশুপাল না পাওয়া গেলে করণীয়। ঠিক আছে এমকিডির। এটিও পারমাণবিক অপারেশন। কেবলমাত্র একটি প্রক্রিয়া সফল এমকেডিরের ফলশ্রুতিতে আসবে, অন্য সমস্ত ব্যর্থ হবে।
সুতরাং কোডটি হ'ল:
if mkdir /var/lock/.myscript.exclusivelock
then
# do stuff
:
rmdir /var/lock/.myscript.exclusivelock
fi
আপনার স্ক্রিপ্ট আর কখনও চালিত হবে না এমন দুর্ঘটনার পরে আপনাকে বাসি লকগুলির যত্ন নেওয়া দরকার।
sleep 10
আগে যুক্ত করুন rmdir
এবং আবার ক্যাসকেড করার চেষ্টা করুন - কিছুই "ফুটো" হবে না।
লকিংকে নির্ভরযোগ্য করে তুলতে আপনার একটি পারমাণবিক অপারেশন প্রয়োজন। উপরোক্ত প্রস্তাবগুলির মধ্যে অনেকগুলি পারমাণবিক নয়। প্রস্তাবিত লকফিল (1) ইউটিলিটিটি ম্যান-পৃষ্ঠাতে উল্লিখিত হিসাবে এটির "এনএফএস-প্রতিরোধী" হিসাবে আশাব্যঞ্জক বলে মনে হচ্ছে। যদি আপনার ওএস লকফিল (1) সমর্থন করে না এবং আপনার সমাধানটি এনএফএসে কাজ করতে হয় তবে আপনার কাছে খুব বেশি বিকল্প নেই ...
এনএফএসভি 2 এর দুটি পরমাণু অপারেশন রয়েছে:
এনএফএসভি 3 এর সাথে তৈরি কলটিও পারমাণবিক।
ডিরেক্টরি ক্রিয়াকলাপগুলি এনএফএসভি 2 এবং এনএফএসভি 3 এর অধীনে পারমাণবিক নয় (অনুগ্রহ করে ব্রেন্ট ক্যালাহান, আইএসবিএন 0-201-32570-5-র লেখা 'এনএফএস ইলাস্ট্রেটেড' বইটি পড়ুন; ব্রেন্ট সান-এ এনএফএস-অভিজ্ঞ))
এটি জানার পরে, আপনি ফাইল এবং ডিরেক্টরিগুলির জন্য স্পিন-লকগুলি প্রয়োগ করতে পারেন (শ্যালে, পিএইচপি নয়):
লক বর্তমান দির:
while ! ln -s . lock; do :; done
একটি ফাইল লক করুন:
while ! ln -s ${f} ${f}.lock; do :; done
আনলক বর্তমান দির (অনুমান, চলমান প্রক্রিয়াটি সত্যিই লকটি অর্জন করেছে):
mv lock deleteme && rm deleteme
একটি ফাইল আনলক করুন (ধারণা, চলমান প্রক্রিয়াটি সত্যিই লকটি অর্জন করেছে):
mv ${f}.lock ${f}.deleteme && rm ${f}.deleteme
অপসারণটিও পারমাণবিক নয়, অতএব প্রথমে পুনরায় নামকরণ (যা পরমাণু) এবং তারপরে অপসারণ।
সিমলিংক এবং পুনঃনামকরণ কলগুলির জন্য, উভয় ফাইলের নাম একই ফাইল সিস্টেমে থাকতে হবে। আমার প্রস্তাব: কেবলমাত্র সরল ফাইলের নাম ব্যবহার করুন (কোনও পাথ নেই) এবং একই ডিরেক্টরিতে ফাইল এবং লক রাখুন।
lockfile
উপলব্ধ হলে এটি ব্যবহার করে , বা symlink
না হলে এই পদ্ধতিতে ফ্যালব্যাক ।
mv
, rm
) এর জন্য, দুটি প্রক্রিয়া পি 1, পি 2 রেসিংয়ের rm -f
পরিবর্তে ব্যবহার করা উচিত rm
? উদাহরণস্বরূপ, পি 1 আনলকটি শুরু করে mv
, তারপরে পি 2 লকগুলি, তারপরে পি 2 আনলক করে (উভয় mv
এবং উভয় rm
), শেষ পর্যন্ত পি 1 প্রচেষ্টা rm
এবং ব্যর্থ হয়।
$$
এ ${f}.deleteme
ফাইলের নাম।
আরেকটি বিকল্প হ'ল চালিয়ে শেলের noclobber
বিকল্পটি ব্যবহার করা set -C
। তারপর >
ব্যর্থ হয়ে যাবে ফাইল ইতিমধ্যেই বিদ্যমান।
সংক্ষেপে:
set -C
lockfile="/tmp/locktest.lock"
if echo "$$" > "$lockfile"; then
echo "Successfully acquired lock"
# do work
rm "$lockfile" # XXX or via trap - see below
else
echo "Cannot acquire lock - already locked by $(cat "$lockfile")"
fi
এটি শেলটি কল করার কারণ দেয়:
open(pathname, O_CREAT|O_EXCL)
যা পরমাণুভাবে ফাইল তৈরি করে বা ফাইলটি ইতিমধ্যে উপস্থিত থাকলে ব্যর্থ হয়।
বাশাএফএউ 045-এর একটি মন্তব্য অনুসারে , এটি ব্যর্থ হতে পারে ksh88
তবে এটি আমার সমস্ত শেলগুলিতে কাজ করে:
$ strace -e trace=creat,open -f /bin/bash /home/mikel/bin/testopen 2>&1 | grep -F testopen.lock
open("/tmp/testopen.lock", O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE, 0666) = 3
$ strace -e trace=creat,open -f /bin/zsh /home/mikel/bin/testopen 2>&1 | grep -F testopen.lock
open("/tmp/testopen.lock", O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_LARGEFILE, 0666) = 3
$ strace -e trace=creat,open -f /bin/pdksh /home/mikel/bin/testopen 2>&1 | grep -F testopen.lock
open("/tmp/testopen.lock", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_LARGEFILE, 0666) = 3
$ strace -e trace=creat,open -f /bin/dash /home/mikel/bin/testopen 2>&1 | grep -F testopen.lock
open("/tmp/testopen.lock", O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE, 0666) = 3
আকর্ষণীয় যা পতাকা pdksh
যুক্ত করে O_TRUNC
, তবে স্পষ্টতই এটি
অনর্থক : হয় আপনি খালি ফাইল তৈরি করছেন, বা আপনি কিছু করছেন না।
আপনি কীভাবে করবেন তা rm
নির্ভর করে আপনি কীভাবে অপরিষ্কার প্রস্থানগুলি পরিচালনা করতে চান তার উপর।
পরিষ্কার প্রস্থান থেকে মুছুন
অশুচি প্রস্থানটি মীমাংসিত হওয়ার কারণে এবং লকফিলটি ম্যানুয়ালি সরানো না হওয়া পর্যন্ত নতুন রান ব্যর্থ হয়।
# acquire lock
# do work (code here may call exit, etc.)
rm "$lockfile"
যে কোনও প্রস্থান থেকে মুছুন
স্ক্রিপ্ট ইতিমধ্যে চালু না থাকলে নতুন রান সফল হয়।
trap 'rm "$lockfile"' EXIT
আপনি GNU Parallel
এটির জন্য যখন এটি ডায়ালিউড হিসাবে মিটেক্স হিসাবে কাজ করে তা ব্যবহার করতে পারেন sem
। সুতরাং, কংক্রিট পদগুলিতে, আপনি ব্যবহার করতে পারেন:
sem --id SCRIPTSINGLETON yourScript
যদি আপনিও একটি সময়সীমা চান, ব্যবহার করুন:
sem --id SCRIPTSINGLETON --semaphoretimeout -10 yourScript
<0 এর টাইমআউটটির অর্থ সময়সীমার মধ্যে যদি semaphore প্রকাশ না করা হয় তবে স্ক্রিপ্টটি চালানো ছাড়াই প্রস্থান করা হবে,> 0 এর টাইমআউটটি যাইহোক স্ক্রিপ্টটি চালান।
মনে রাখবেন যে এটির একটি নাম দেওয়া উচিত (সহ --id
) অন্যথায় এটি নিয়ন্ত্রণকারী টার্মিনালটিতে ডিফল্ট হয়।
GNU Parallel
বেশিরভাগ লিনাক্স / ওএসএক্স / ইউনিক্স প্ল্যাটফর্মগুলিতে একটি খুব সহজ ইনস্টল - এটি কেবল পার্ল স্ক্রিপ্ট।
sem
সম্পর্কিত প্রশ্নটিতে আরও unix.stackexchange.com/a/322200/199525 ।
শেল স্ক্রিপ্টগুলির জন্য, আমি mkdir
ওভারের সাথে যেতে চাই flock
কারণ এটি লকগুলি আরও পোর্টেবল করে তোলে।
যেভাবেই হোক, ব্যবহার set -e
করা যথেষ্ট নয়। কোনও কমান্ড ব্যর্থ হলে এটি কেবল স্ক্রিপ্ট থেকে প্রস্থান করে। আপনার লকগুলি এখনও পিছনে থাকবে।
যথাযথ লক ক্লিনআপের জন্য, আপনার সত্যিকার অর্থে আপনার এই ফাঁদগুলি এই স্যুয়েডো কোডের মতো সেট করা উচিত (উত্তোলন, সরলীকৃত এবং অনির্ধারিত তবে সক্রিয়ভাবে ব্যবহৃত স্ক্রিপ্টগুলি থেকে):
#=======================================================================
# Predefined Global Variables
#=======================================================================
TMPDIR=/tmp/myapp
[[ ! -d $TMP_DIR ]] \
&& mkdir -p $TMP_DIR \
&& chmod 700 $TMPDIR
LOCK_DIR=$TMP_DIR/lock
#=======================================================================
# Functions
#=======================================================================
function mklock {
__lockdir="$LOCK_DIR/$(date +%s.%N).$$" # Private Global. Use Epoch.Nano.PID
# If it can create $LOCK_DIR then no other instance is running
if $(mkdir $LOCK_DIR)
then
mkdir $__lockdir # create this instance's specific lock in queue
LOCK_EXISTS=true # Global
else
echo "FATAL: Lock already exists. Another copy is running or manually lock clean up required."
exit 1001 # Or work out some sleep_while_execution_lock elsewhere
fi
}
function rmlock {
[[ ! -d $__lockdir ]] \
&& echo "WARNING: Lock is missing. $__lockdir does not exist" \
|| rmdir $__lockdir
}
#-----------------------------------------------------------------------
# Private Signal Traps Functions {{{2
#
# DANGER: SIGKILL cannot be trapped. So, try not to `kill -9 PID` or
# there will be *NO CLEAN UP*. You'll have to manually remove
# any locks in place.
#-----------------------------------------------------------------------
function __sig_exit {
# Place your clean up logic here
# Remove the LOCK
[[ -n $LOCK_EXISTS ]] && rmlock
}
function __sig_int {
echo "WARNING: SIGINT caught"
exit 1002
}
function __sig_quit {
echo "SIGQUIT caught"
exit 1003
}
function __sig_term {
echo "WARNING: SIGTERM caught"
exit 1015
}
#=======================================================================
# Main
#=======================================================================
# Set TRAPs
trap __sig_exit EXIT # SIGEXIT
trap __sig_int INT # SIGINT
trap __sig_quit QUIT # SIGQUIT
trap __sig_term TERM # SIGTERM
mklock
# CODE
exit # No need for cleanup code here being in the __sig_exit trap function
এখানে কি হবে। সমস্ত ট্র্যাপগুলি একটি প্রস্থান তৈরি করবে যাতে ফাংশনটি __sig_exit
সর্বদা ঘটে (সিক্কিল বাদে) যা আপনার লকগুলি পরিষ্কার করে।
দ্রষ্টব্য: আমার প্রস্থান মানগুলি কম মান নয়। কেন? বিভিন্ন ব্যাচ প্রসেসিং সিস্টেমগুলি 0 থেকে 31 এর মধ্যে সংখ্যার প্রত্যাশা তৈরি করে বা তাদের কাছে প্রত্যাশা রাখে them এগুলিকে অন্য কিছুতে সেট করে, আমার স্ক্রিপ্টগুলি এবং ব্যাচ স্ট্রিমগুলি পূর্ববর্তী ব্যাচের কাজ বা স্ক্রিপ্ট অনুসারে প্রতিক্রিয়া জানাতে পারে।
rm -r $LOCK_DIR
বা এমনকি প্রয়োজনীয় যেমন ফোর্স (যেমন আমি যেমন আপেক্ষিক আঁচড়ের দাগ ফাইল অধিষ্ঠিত যেমন বিশেষ ক্ষেত্রে খুব কাজ করেছেন)। চিয়ার্স।
exit 1002
?
সত্যিই দ্রুত এবং সত্যিই নোংরা? আপনার স্ক্রিপ্টের শীর্ষে এই ওয়ান-লাইনারটি কাজ করবে:
[[ $(pgrep -c "`basename \"$0\"`") -gt 1 ]] && exit
অবশ্যই, নিশ্চিত করুন যে আপনার স্ক্রিপ্টের নামটি অনন্য। :)
-gt 2
? গ্রেপ সবসময় পিএস এর ফলাফলের মধ্যে নিজেকে খুঁজে পায় না!
pgrep
পসিক্সে নেই। আপনি যদি এটিকে বহনযোগ্যভাবে কাজ করতে চান তবে আপনার পসিক্স প্রয়োজন ps
এবং এর আউটপুট প্রক্রিয়া করা উচিত ।
-c
বিদ্যমান নেই, আপনাকে ব্যবহার করতে হবে | wc -l
। সংখ্যার তুলনা সম্পর্কে: -gt 1
প্রথম উদাহরণটি নিজে দেখায় যেহেতু চেক করা হয়।
এখানে একটি পদ্ধতির সাথে পারমাণবিক ডিরেক্টরি লকিংয়ের সাথে PID এর মাধ্যমে বাসি লকটির জন্য একটি চেক সংযুক্ত করা হয় এবং বাসি হলে পুনরায় চালু করা যায়। এছাড়াও, এটি কোনও বাশমের উপর নির্ভর করে না।
#!/bin/dash
SCRIPTNAME=$(basename $0)
LOCKDIR="/var/lock/${SCRIPTNAME}"
PIDFILE="${LOCKDIR}/pid"
if ! mkdir $LOCKDIR 2>/dev/null
then
# lock failed, but check for stale one by checking if the PID is really existing
PID=$(cat $PIDFILE)
if ! kill -0 $PID 2>/dev/null
then
echo "Removing stale lock of nonexistent PID ${PID}" >&2
rm -rf $LOCKDIR
echo "Restarting myself (${SCRIPTNAME})" >&2
exec "$0" "$@"
fi
echo "$SCRIPTNAME is already running, bailing out" >&2
exit 1
else
# lock successfully acquired, save PID
echo $$ > $PIDFILE
fi
trap "rm -rf ${LOCKDIR}" QUIT INT TERM EXIT
echo hello
sleep 30s
echo bye
এই উদাহরণটি ম্যান ফ্লকের মধ্যে ব্যাখ্যা করা হয়েছে, তবে এটির জন্য কিছু উন্নতি প্রয়োজন, কারণ আমাদের বাগ এবং প্রস্থান কোডগুলি পরিচালনা করা উচিত:
#!/bin/bash
#set -e this is useful only for very stupid scripts because script fails when anything command exits with status more than 0 !! without possibility for capture exit codes. not all commands exits >0 are failed.
( #start subprocess
# Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
flock -x -w 10 200
if [ "$?" != "0" ]; then echo Cannot lock!; exit 1; fi
echo $$>>/var/lock/.myscript.exclusivelock #for backward lockdir compatibility, notice this command is executed AFTER command bottom ) 200>/var/lock/.myscript.exclusivelock.
# Do stuff
# you can properly manage exit codes with multiple command and process algorithm.
# I suggest throw this all to external procedure than can properly handle exit X commands
) 200>/var/lock/.myscript.exclusivelock #exit subprocess
FLOCKEXIT=$? #save exitcode status
#do some finish commands
exit $FLOCKEXIT #return properly exitcode, may be usefull inside external scripts
আপনি অন্য পদ্ধতি ব্যবহার করতে পারেন, অতীতে আমি যে প্রক্রিয়াগুলি ব্যবহার করেছি তার তালিকা তৈরি করুন। তবে এটি উপরে যে পদ্ধতিটি আরও জটিল। আপনার পিএস দ্বারা প্রক্রিয়াগুলি তালিকাভুক্ত করা উচিত, তার নাম অনুসারে ফিল্টার করুন, পরজীবী নাদ অপসারণের জন্য অতিরিক্ত ফিল্টার গ্রেপ-ভি গ্রেপ অবশেষে এটিকে গ্রেপ-সি দ্বারা গণনা করুন। এবং সংখ্যার সাথে তুলনা করুন। এটি জটিল এবং অনিশ্চিত
বিদ্যমান উত্তরগুলি হয় হয় সি এল এল ইউটিলিটির উপর নির্ভর করে flock
বা লক ফাইলটি সঠিকভাবে সুরক্ষিত করে না। সমস্ত নন-লিনাক্স সিস্টেমে (যেমন ফ্রিবিএসডি) ফ্লকের ইউটিলিটি উপলব্ধ নেই এবং এনএফএসে সঠিকভাবে কাজ করে না।
সিস্টেম প্রশাসন এবং সিস্টেম বিকাশের আমার প্রথম দিনগুলিতে আমাকে বলা হয়েছিল যে লক ফাইল তৈরির একটি নিরাপদ এবং তুলনামূলকভাবে বহনযোগ্য পদ্ধতিটি টেম্প ফাইল (অর্থাত্ পিআইডি) তে সনাক্তকারী তথ্য লিখতে mkemp(3)
বা mkemp(1)
তারপরে শক্ত লিঙ্কটি ব্যবহার করে একটি টেম্প ফাইল তৈরি করা ছিল then লক ফাইলটিতে অস্থায়ী ফাইল। লিঙ্কটি সফল হলে, আপনি সফলভাবে লকটি পেয়েছেন।
শেল স্ক্রিপ্টগুলিতে লক ব্যবহার করার সময়, আমি সাধারণত obtain_lock()
একটি ভাগ করা প্রোফাইলে একটি ফাংশন রাখি এবং তারপরে স্ক্রিপ্টগুলি থেকে উত্স করি। নীচে আমার লক ফাংশনের উদাহরণ দেওয়া হল:
obtain_lock()
{
LOCK="${1}"
LOCKDIR="$(dirname "${LOCK}")"
LOCKFILE="$(basename "${LOCK}")"
# create temp lock file
TMPLOCK=$(mktemp -p "${LOCKDIR}" "${LOCKFILE}XXXXXX" 2> /dev/null)
if test "x${TMPLOCK}" == "x";then
echo "unable to create temporary file with mktemp" 1>&2
return 1
fi
echo "$$" > "${TMPLOCK}"
# attempt to obtain lock file
ln "${TMPLOCK}" "${LOCK}" 2> /dev/null
if test $? -ne 0;then
rm -f "${TMPLOCK}"
echo "unable to obtain lockfile" 1>&2
if test -f "${LOCK}";then
echo "current lock information held by: $(cat "${LOCK}")" 1>&2
fi
return 2
fi
rm -f "${TMPLOCK}"
return 0;
};
নিম্নলিখিতটি কীভাবে লক ফাংশনটি ব্যবহার করবেন তার একটি উদাহরণ:
#!/bin/sh
. /path/to/locking/profile.sh
PROG_LOCKFILE="/tmp/myprog.lock"
clean_up()
{
rm -f "${PROG_LOCKFILE}"
}
obtain_lock "${PROG_LOCKFILE}"
if test $? -ne 0;then
exit 1
fi
trap clean_up SIGHUP SIGINT SIGTERM
# bulk of script
clean_up
exit 0
# end of script
clean_up
আপনার স্ক্রিপ্টের যে কোনও প্রস্থান পয়েন্টে কল করতে ভুলবেন না।
আমি লিনাক্স এবং ফ্রিবিএসডি উভয় পরিবেশে উপরোক্ত ব্যবহার করেছি।
কোনও ডেবিয়ান মেশিনকে টার্গেট করার সময় আমি lockfile-progs
প্যাকেজটিকে একটি ভাল সমাধান বলে মনে করি। procmail
এছাড়াও একটি lockfile
সরঞ্জাম সঙ্গে আসে । তবে মাঝে মাঝে আমি এগুলির কোনওটির সাথেই আটকে থাকি।
এখানে আমার সমাধান যা mkdir
বায়ুযুক্ত লকগুলি সনাক্ত করতে পারমাণবিক নেস এবং একটি পিআইডি ফাইল ব্যবহার করে। এই কোডটি বর্তমানে সাইগউইন সেটআপে প্রস্তুত এবং ভালভাবে কাজ করে।
এটি ব্যবহার করার জন্য exclusive_lock_require
যখন আপনার কোনও কিছুর একচেটিয়া অ্যাক্সেসের প্রয়োজন হয় তখনই কল করুন । একটি alচ্ছিক লক নামের প্যারামিটার আপনাকে বিভিন্ন স্ক্রিপ্টগুলির মধ্যে লকগুলি ভাগ করতে দেয়। নিম্ন স্তরের দুটি কার্যও রয়েছে ( exclusive_lock_try
এবং exclusive_lock_retry
) আপনার আরও জটিল কিছু প্রয়োজন।
function exclusive_lock_try() # [lockname]
{
local LOCK_NAME="${1:-`basename $0`}"
LOCK_DIR="/tmp/.${LOCK_NAME}.lock"
local LOCK_PID_FILE="${LOCK_DIR}/${LOCK_NAME}.pid"
if [ -e "$LOCK_DIR" ]
then
local LOCK_PID="`cat "$LOCK_PID_FILE" 2> /dev/null`"
if [ ! -z "$LOCK_PID" ] && kill -0 "$LOCK_PID" 2> /dev/null
then
# locked by non-dead process
echo "\"$LOCK_NAME\" lock currently held by PID $LOCK_PID"
return 1
else
# orphaned lock, take it over
( echo $$ > "$LOCK_PID_FILE" ) 2> /dev/null && local LOCK_PID="$$"
fi
fi
if [ "`trap -p EXIT`" != "" ]
then
# already have an EXIT trap
echo "Cannot get lock, already have an EXIT trap"
return 1
fi
if [ "$LOCK_PID" != "$$" ] &&
! ( umask 077 && mkdir "$LOCK_DIR" && umask 177 && echo $$ > "$LOCK_PID_FILE" ) 2> /dev/null
then
local LOCK_PID="`cat "$LOCK_PID_FILE" 2> /dev/null`"
# unable to acquire lock, new process got in first
echo "\"$LOCK_NAME\" lock currently held by PID $LOCK_PID"
return 1
fi
trap "/bin/rm -rf \"$LOCK_DIR\"; exit;" EXIT
return 0 # got lock
}
function exclusive_lock_retry() # [lockname] [retries] [delay]
{
local LOCK_NAME="$1"
local MAX_TRIES="${2:-5}"
local DELAY="${3:-2}"
local TRIES=0
local LOCK_RETVAL
while [ "$TRIES" -lt "$MAX_TRIES" ]
do
if [ "$TRIES" -gt 0 ]
then
sleep "$DELAY"
fi
local TRIES=$(( $TRIES + 1 ))
if [ "$TRIES" -lt "$MAX_TRIES" ]
then
exclusive_lock_try "$LOCK_NAME" > /dev/null
else
exclusive_lock_try "$LOCK_NAME"
fi
LOCK_RETVAL="${PIPESTATUS[0]}"
if [ "$LOCK_RETVAL" -eq 0 ]
then
return 0
fi
done
return "$LOCK_RETVAL"
}
function exclusive_lock_require() # [lockname] [retries] [delay]
{
if ! exclusive_lock_retry "$@"
then
exit 1
fi
}
যদি এই থ্রেডটিতে ইতিমধ্যে অন্য কোথাও বর্ণিত পালের সীমাবদ্ধতাগুলি আপনার পক্ষে সমস্যা না হয়, তবে এটি কাজ করা উচিত:
#!/bin/bash
{
# exit if we are unable to obtain a lock; this would happen if
# the script is already running elsewhere
# note: -x (exclusive) is the default
flock -n 100 || exit
# put commands to run here
sleep 100
} 100>/tmp/myjob.lock
-n
হবে exit 1
অবিলম্বে যদি এটা লক পেতে পারে না
কিছু unixes আছে lockfile
যা খুব ইতিমধ্যে উল্লিখিত অনুরূপ flock
।
ম্যানপেজ থেকে:
এক বা একাধিক সেমফোর ফাইল তৈরি করতে লকফিল ব্যবহার করা যেতে পারে। যদি লক-ফাইলটি সমস্ত নির্দিষ্ট ফাইল তৈরি করতে না পারে (নির্দিষ্ট ক্রমে), এটি স্লিপটাইম (8 ডিফল্টে ডিফল্ট) সেকেন্ডে অপেক্ষা করে এবং সফল হওয়াতে শেষ ফাইলটি পুনরায় চেষ্টা করে। ব্যর্থতা ফিরে না আসা পর্যন্ত আপনি করার চেষ্টাগুলি উল্লেখ করতে পারেন। যদি পুনরায় চেষ্টা করার সংখ্যা -1 হয় (ডিফল্ট, অর্থাত, -r-1) লকফিল চিরতরে আবার চেষ্টা করবে।
lockfile
ইউটিলিটি পাবেন ??
lockfile
দিয়ে বিতরণ করা হয় procmail
। এছাড়াও প্যাকেজ dotlockfile
সহ একটি বিকল্প আছে liblockfile
। তারা উভয়ই এনএফএসে নির্ভরযোগ্যভাবে কাজ করার দাবি করে।
আসলে যদিও বিএমড্যাক্সের উত্তর প্রায় ভাল, প্রথম লকফায়ালটি পরীক্ষা করার পরে এবং এটি লেখার আগে দ্বিতীয় স্ক্রিপ্টটি চালানোর সামান্য সম্ভাবনা রয়েছে। সুতরাং তারা দুজনেই লক ফাইলটি লিখবে এবং তারা উভয়ই চলবে। এটি নিশ্চিতভাবে কীভাবে কাজ করা যায় তা এখানে:
lockfile=/var/lock/myscript.lock
if ( set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null ; then
trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT
else
# or you can decide to skip the "else" part if you want
echo "Another instance is already running!"
fi
noclobber
বিকল্প নিশ্চিত যদি ফাইল আগে থেকেই আছে যে পুনর্নির্দেশ কমান্ড ব্যর্থ হবে করতে হবে। পুনঃনির্দেশ কমান্ডটি আসলে পারমাণবিক - আপনি একটি কমান্ড দিয়ে ফাইলটি লিখে পরীক্ষা করে দেখুন। আপনার ফাইলের শেষে লকফিলটি সরানোর দরকার নেই - এটি ফাঁদে ফেলে দেওয়া হবে। আমি আশা করি এটি এমন লোকদের সহায়তা করে যা এটি পরে পড়বে।
পিএস আমি দেখতে পাইনি যে মাইকেল ইতিমধ্যে প্রশ্নের সঠিক উত্তর দিয়েছেন, যদিও তিনি ট্র্যাক কমান্ডটি অন্তর্ভুক্ত করেননি উদাহরণস্বরূপ Ctrl-C এর সাথে স্ক্রিপ্টটি থামানোর পরে লক ফাইলটি ফেলে দেওয়ার সম্ভাবনা কমাতে। সুতরাং এটি সম্পূর্ণ সমাধান
আমি লকফিলস, লকডিয়ারস, বিশেষ লকিং প্রোগ্রামগুলি এবং pidof
সমস্ত লিনাক্স ইনস্টলেশনে পাওয়া যায়নি এমনটি সরিয়ে ফেলতে চেয়েছিলাম । সহজতম কোডটিও (বা কমপক্ষে কম কয়েকটি লাইন সম্ভব হিসাবে) পেতে চেয়েছিলেন। if
এক লাইনে সহজ বক্তব্য:
if [[ $(ps axf | awk -v pid=$$ '$1!=pid && $6~/'$(basename $0)'/{print $1}') ]]; then echo "Already running"; exit; fi
/bin/ps -a --format pid,cmd | awk -v pid=$$ '/'$(basename $0)'/ { if ($1!=pid) print $1; }'
আমি একটি সাধারণ পদ্ধতির ব্যবহার করি যা বাসি লক ফাইলগুলি পরিচালনা করে।
লক্ষ্য করুন যে উপরের কয়েকটি সমাধান যা পিড সংরক্ষণ করে, পিডটি প্রায় মোড়ানো করতে পারে তা উপেক্ষা করুন। সুতরাং - সঞ্চিত পিডের সাথে কোনও বৈধ প্রক্রিয়া রয়েছে কিনা তা পরীক্ষা করা যথেষ্ট নয়, বিশেষত দীর্ঘস্থায়ী স্ক্রিপ্টগুলির জন্য।
আমি একবারে শুধুমাত্র একটি স্ক্রিপ্ট লক ফাইলটিতে খুলতে এবং লিখতে পারি তা নিশ্চিত করার জন্য নোক্লোবার ব্যবহার করি। তদ্ব্যতীত, আমি লকফাইলে একটি প্রক্রিয়া অনন্যরূপে সনাক্ত করতে পর্যাপ্ত তথ্য সঞ্চয় করি। পিড, পিপিড, lstart হওয়ার প্রক্রিয়াটিকে অনন্যভাবে সনাক্ত করতে আমি ডেটার সেটটিকে সংজ্ঞায়িত করি।
যখন একটি নতুন স্ক্রিপ্ট শুরু হবে, যদি এটি লক ফাইলটি তৈরি করতে ব্যর্থ হয়, তখন এটি যাচাই করে যে লক ফাইলটি তৈরি করার প্রক্রিয়াটি এখনও রয়েছে। যদি তা না হয় তবে আমরা ধরে নিই যে মূল প্রক্রিয়াটি একটি কৃত্রিম মৃত্যুবরণ করেছে, এবং একটি বাসি লক ফাইলটি রেখে গেছে। এরপরে নতুন স্ক্রিপ্টটি লক ফাইলটির মালিকানা গ্রহণ করবে এবং সমস্ত কিছু আবার ভাল।
একাধিক প্ল্যাটফর্ম জুড়ে একাধিক শেল নিয়ে কাজ করা উচিত। দ্রুত, পোর্টেবল এবং সহজ।
#!/usr/bin/env sh
# Author: rouble
LOCKFILE=/var/tmp/lockfile #customize this line
trap release INT TERM EXIT
# Creates a lockfile. Sets global variable $ACQUIRED to true on success.
#
# Returns 0 if it is successfully able to create lockfile.
acquire () {
set -C #Shell noclobber option. If file exists, > will fail.
UUID=`ps -eo pid,ppid,lstart $$ | tail -1`
if (echo "$UUID" > "$LOCKFILE") 2>/dev/null; then
ACQUIRED="TRUE"
return 0
else
if [ -e $LOCKFILE ]; then
# We may be dealing with a stale lock file.
# Bring out the magnifying glass.
CURRENT_UUID_FROM_LOCKFILE=`cat $LOCKFILE`
CURRENT_PID_FROM_LOCKFILE=`cat $LOCKFILE | cut -f 1 -d " "`
CURRENT_UUID_FROM_PS=`ps -eo pid,ppid,lstart $CURRENT_PID_FROM_LOCKFILE | tail -1`
if [ "$CURRENT_UUID_FROM_LOCKFILE" == "$CURRENT_UUID_FROM_PS" ]; then
echo "Script already running with following identification: $CURRENT_UUID_FROM_LOCKFILE" >&2
return 1
else
# The process that created this lock file died an ungraceful death.
# Take ownership of the lock file.
echo "The process $CURRENT_UUID_FROM_LOCKFILE is no longer around. Taking ownership of $LOCKFILE"
release "FORCE"
if (echo "$UUID" > "$LOCKFILE") 2>/dev/null; then
ACQUIRED="TRUE"
return 0
else
echo "Cannot write to $LOCKFILE. Error." >&2
return 1
fi
fi
else
echo "Do you have write permissons to $LOCKFILE ?" >&2
return 1
fi
fi
}
# Removes the lock file only if this script created it ($ACQUIRED is set),
# OR, if we are removing a stale lock file (first parameter is "FORCE")
release () {
#Destroy lock file. Take no prisoners.
if [ "$ACQUIRED" ] || [ "$1" == "FORCE" ]; then
rm -f $LOCKFILE
fi
}
# Test code
# int main( int argc, const char* argv[] )
echo "Acquring lock."
acquire
if [ $? -eq 0 ]; then
echo "Acquired lock."
read -p "Press [Enter] key to release lock..."
release
echo "Released lock."
else
echo "Unable to acquire lock."
fi
আপনার স্ক্রিপ্টের শুরুতে এই লাইনটি যুক্ত করুন
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :
এটি ম্যান ফ্লকের একটি বয়লারপ্লেট কোড।
আপনি যদি আরও লগিং করতে চান তবে এটি ব্যবহার করুন
[ "${FLOCKER}" != "$0" ] && { echo "Trying to start build from queue... "; exec bash -c "FLOCKER='$0' flock -E $E_LOCKED -en '$0' '$0' '$@' || if [ \"\$?\" -eq $E_LOCKED ]; then echo 'Locked.'; fi"; } || echo "Lock is free. Completing."
এটি flock
ইউটিলিটি ব্যবহার করে লকগুলি সেট এবং চেক করে । এই কোডটি এটি প্রথমবারে ফ্লোকার ভেরিয়েবলটি পরীক্ষা করে চালানো হয়েছিল কিনা তা সনাক্ত করে, যদি এটি স্ক্রিপ্টের নাম হিসাবে সেট না করা থাকে, তবে এটি পুনরায় পুনরুত্প্রকারভাবে ঝাঁক ব্যবহার করে এবং FLOCKER ভেরিয়েবল আরম্ভকরণের চেষ্টা করে, যদি FLOCKER সঠিকভাবে সেট করা থাকে, তবে পূর্ববর্তী পুনরাবৃত্তিতে ফ্লক করুন সফল এবং এটি এগিয়ে যেতে ঠিক আছে। লক ব্যস্ত থাকলে, এটি কনফিগারযোগ্য প্রস্থান কোডের সাথে ব্যর্থ হয়।
এটি ডেবিয়ান 7 এ কাজ করছে না বলে মনে হচ্ছে, তবে পরীক্ষামূলক ইউজ-লিনাক্স 2.25 প্যাকেজটি নিয়ে আবার কাজ করবে বলে মনে হচ্ছে। এটি "ফ্লক: ... টেক্সট ফাইল ব্যস্ত" লিখেছেন। এটি আপনার স্ক্রিপ্টে লেখার অনুমতি অক্ষম করে ওভাররাইড করা যেতে পারে।
পিআইডি এবং লকফিলগুলি অবশ্যই সবচেয়ে নির্ভরযোগ্য। আপনি যখন প্রোগ্রামটি চালানোর চেষ্টা করছেন, এটি লকফাইলে যা যা এবং এটি বিদ্যমান থাকলে তা পরীক্ষা করতে পারে ps
যে প্রক্রিয়াটি এখনও চলছে কিনা তা দেখতে এটি ব্যবহার করতে পারে । যদি এটি না হয় তবে স্ক্রিপ্টটি শুরু করতে পারে, লকফাইলে থাকা পিআইডিটিকে নিজস্ব হিসাবে আপডেট করে।
আমি দেখতে পেয়েছি যে কমপক্ষে আমার ব্যবহারের ক্ষেত্রে বিএমড্যাকের সমাধানটি সবচেয়ে ব্যবহারিক। ফ্লক এবং লকফিল ব্যবহার করে স্ক্রিপ্টটি সমাপ্ত হলে লকফায়ালটি আরএম ব্যবহার করে মুছে ফেলার উপর নির্ভর করে, যা সর্বদা গ্যারান্টিযুক্ত হতে পারে না (যেমন, কিল -9)।
আমি বিএমড্যাকের সমাধান সম্পর্কে একটি ছোটখাটো জিনিস পরিবর্তন করব: এটি লক ফাইলটি সরিয়ে ফেলার বিষয়টি তুলে ধরেছে, এটি উল্লেখ না করেই যে এই سيمফোরের নিরাপদ কাজের জন্য এটি অপ্রয়োজনীয়। তাঁর কিল -0-এর ব্যবহার নিশ্চিত করে যে একটি মৃত প্রক্রিয়ার জন্য একটি পুরানো লকফিল কেবল উপেক্ষা / অতিরিক্ত লিখিত হবে।
আমার সরলিকৃত সমাধানটি কেবলমাত্র আপনার সিঙ্গলটনের শীর্ষে নিম্নলিখিতটি যুক্ত করার জন্য:
## Test the lock
LOCKFILE=/tmp/singleton.lock
if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then
echo "Script already running. bye!"
exit
fi
## Set the lock
echo $$ > ${LOCKFILE}
অবশ্যই, এই স্ক্রিপ্টটিতে এখনও ত্রুটি রয়েছে যা একই সময়ে শুরু হওয়ার সম্ভাবনা রয়েছে এমন প্রক্রিয়াগুলির একটি রেসের ঝুঁকি রয়েছে, কারণ লক পরীক্ষা এবং সেট অপারেশনগুলি কোনও একক পারমাণবিক ক্রিয়া নয়। তবে লুনাথের এমকেডির ব্যবহারের প্রস্তাবিত সমাধানটিতে একটি ত্রুটি রয়েছে যে একটি নিহত স্ক্রিপ্টটি ডিরেক্টরিতে রেখে যেতে পারে, ফলে অন্যান্য দৃষ্টান্তগুলি চলতে বাধা দেয়।
Semaphoric ইউটিলিটি ব্যবহার flock
(যেমন presto8 করে উপরের আলোচনা, যেমন) একটি বাস্তবায়ন কাউন্টিং সেমফোর্ । এটি আপনার চাইলে যে কোনও নির্দিষ্ট সংখ্যক সমসাময়িক প্রক্রিয়া সক্ষম করে। আমরা বিভিন্ন সারিবদ্ধ কর্মী প্রক্রিয়াগুলির সম্মতি স্তরকে সীমাবদ্ধ করতে এটি ব্যবহার করি।
এটি sem এর মতো তবে অনেক বেশি হালকা ওজনের। (সম্পূর্ণ প্রকাশ: Sem সন্ধানের পরে এটি লিখেছিলাম এটি আমাদের প্রয়োজনের জন্য খুব ভারী ছিল এবং সেখানে একটি সাধারণ গণনা সেমফোর ইউটিলিটি উপলব্ধ ছিল না।)
পালের সাথে একটি উদাহরণ (1) তবে সাব শীল ছাড়াই। flock () এডি ফাইল / tmp / foo কখনই সরানো হয় না, তবে এটি flock () এবং un-flock () এড হওয়ার সাথে কিছু যায় আসে না।
#!/bin/bash
exec 9<> /tmp/foo
flock -n 9
RET=$?
if [[ $RET -ne 0 ]] ; then
echo "lock failed, exiting"
exit
fi
#Now we are inside the "critical section"
echo "inside lock"
sleep 5
exec 9>&- #close fd 9, and release lock
#The part below is outside the critical section (the lock)
echo "lock released"
sleep 5
ইতিমধ্যে এক মিলিয়ন বার উত্তর দেওয়া হয়েছে, তবে অন্য উপায়, বাহ্যিক নির্ভরতার প্রয়োজন ছাড়াই:
LOCK_FILE="/var/lock/$(basename "$0").pid"
trap "rm -f ${LOCK_FILE}; exit" INT TERM EXIT
if [[ -f $LOCK_FILE && -d /proc/`cat $LOCK_FILE` ]]; then
// Process already exists
exit 1
fi
echo $$ > $LOCK_FILE
প্রতিবার এটি বর্তমান পিআইডি ($$) লকফাইলে এবং স্ক্রিপ্ট স্টার্টআপ চেকগুলিতে সর্বশেষ পিআইডি সহ কোনও প্রক্রিয়া চলছে কিনা তা লেখায়।
প্রক্রিয়াটির লকটি ব্যবহার করা আরও শক্তিশালী এবং কদর্য প্রস্থানগুলিও যত্ন করে। লক_ফাইলে যতক্ষণ প্রক্রিয়া চলছে ততক্ষণ খোলা রাখা হবে। প্রক্রিয়াটি উপস্থিত হয়ে গেলে এটি (শেল দ্বারা) বন্ধ হয়ে যাবে (এটি মারা গেলেও)। আমি এটি খুব দক্ষ বলে মনে করেছি:
lock_file=/tmp/`basename $0`.lock
if fuser $lock_file > /dev/null 2>&1; then
echo "WARNING: Other instance of $(basename $0) running."
exit 1
fi
exec 3> $lock_file
আমি স্ক্রিপ্টের একেবারে শুরুতে অনেলাইনার @ ব্যবহার করি:
#!/bin/bash
if [[ $(pgrep -afc "$(basename "$0")") -gt "1" ]]; then echo "Another instance of "$0" has already been started!" && exit; fi
.
the_beginning_of_actual_script
মেমোরিতে প্রক্রিয়াটির উপস্থিতি দেখে ভাল হয় (প্রক্রিয়াটির স্থিতিটি যাই হোক না কেন); তবে এটি আমার জন্য কাজ করে।
পালের পথই চলার পথ। স্ক্রিপ্টটি হঠাৎ মারা গেলে কী ঘটে তা ভেবে দেখুন। পশুর ক্ষেত্রে আপনি কেবল ঝাঁক ঝাঁকিয়েছেন, তবে এটি কোনও সমস্যা নয়। এছাড়াও, নোট করুন যে একটি অশুভ কৌশল হ'ল স্ক্রিপ্টে নিজেই একটি ঝাঁক নিয়ে যাওয়া .. তবে অবশ্যই অনুমতি সংক্রান্ত সমস্যার জন্য আপনাকে পুরো বাষ্পে চালিয়ে যেতে দেয়।
দ্রুত এবং ময়লা?
#!/bin/sh
if [ -f sometempfile ]
echo "Already running... will now terminate."
exit
else
touch sometempfile
fi
..do what you want here..
rm sometempfile