শেল স্ক্রিপ্টগুলিতে সঠিক লকিং?


66

কখনও কখনও আপনাকে নিশ্চিত করতে হবে যে শেল স্ক্রিপ্টের কেবলমাত্র একটি উদাহরণ একই সময়ে চলমান।

উদাহরণস্বরূপ একটি ক্রোন জব যা ক্রন্ডের মাধ্যমে সম্পাদিত হয় যা নিজস্বভাবে লকিং সরবরাহ করে না (যেমন ডিফল্ট সোলারিস ক্রন্ড)।

লকিং বাস্তবায়নের একটি সাধারণ প্যাটার্ন হ'ল এই কোড:

#!/bin/sh
LOCK=/var/tmp/mylock
if [ -f $LOCK ]; then            # 'test' -> race begin
  echo Job is already running\!
  exit 6
fi
touch $LOCK                      # 'set'  -> race end
# do some work
rm $LOCK

অবশ্যই, এই জাতীয় কোডটির একটি রেসের শর্ত রয়েছে। একটি সময় উইন্ডো রয়েছে যেখানে দুটি দৃষ্টান্ত প্রয়োগের ফলে $LOCKফাইলটি স্পর্শ করতে সক্ষম হওয়ার আগে উভয়ই 3 লাইনের পরে এগিয়ে যেতে পারে ।

ক্রোন কাজের জন্য এটি সাধারণত কোনও সমস্যা হয় না কারণ আপনার দুটি নিমন্ত্রণের মধ্যে কয়েক মিনিটের ব্যবধান থাকে।

তবে জিনিসগুলি ভুল হতে পারে - উদাহরণস্বরূপ যখন লকফিলটি কোনও এনএফএস সার্ভারে থাকে - যা স্তব্ধ হয়ে যায়। সেক্ষেত্রে বেশ কয়েকটি ক্রোন জব 3 লাইন অবরুদ্ধ করতে এবং সারি করতে পারে। যদি এনএফএস সার্ভারটি আবার সক্রিয় থাকে তবে আপনার সমান্তরাল চলমান কাজের ঝাঁকুনি রয়েছে

ওয়েবে অনুসন্ধান করে আমি সরঞ্জামটি লক্করনের সন্ধান পেয়েছি যা মনে হয় যে সমস্যার সমাধানের ভাল সমাধান বলে মনে হচ্ছে। এটির সাহায্যে আপনি এমন একটি স্ক্রিপ্ট চালান যা এর জন্য লক করা দরকার:

$ lockrun --lockfile=/var/tmp/mylock myscript.sh

আপনি এটি একটি মোড়কে রাখতে পারেন বা এটি আপনার ক্রন্টব থেকে ব্যবহার করতে পারেন।

এটি lockf()উপলব্ধ হলে (পসিক্স) ব্যবহার করে এবং পিছনে পড়ে flock()(বিএসডি)। এবং lockf()এনএফএসের উপর সমর্থন তুলনামূলকভাবে বিস্তৃত হওয়া উচিত।

এর বিকল্প আছে lockrunকি?

অন্যান্য ক্রোন ডেমন সম্পর্কে কী? এমন কি সাধারণ ক্রন্ডস রয়েছে যেগুলি একটি বুদ্ধিমান উপায়ে লকিং সমর্থন করে? ভিক্সি ক্রন্ডের ম্যান পেজটিতে একটি তদন্ত (ডেবিয়ান / উবুন্টু সিস্টেমে ডিফল্ট) লক করার বিষয়ে কিছুই দেখায় না।

এটি একটি ভাল ধারণা মত একটি টুল অন্তর্ভুক্ত করা হবে lockrunমধ্যে coreutils ?

আমার মতে এটা খুব অনুরূপ একটি থিম প্রয়োগ timeout, niceএবং বন্ধুদের।


4
স্পর্শকাতরভাবে এবং অন্যদের উপকারের জন্য যারা আপনার প্রাথমিক প্যাটার্নকে গুড এনাফ (টিএম) বিবেচনা করতে পারে, সেই শেল কোডটি সম্ভবত এডের সময় লকফিলটি অপসারণ করার জন্য TERM কে ফাঁদে ফেলতে হবে kill; এবং নিজের পিডটিকে কেবল স্পর্শ না করে লকফাইলে সংরক্ষণ করা ভাল অনুশীলন বলে মনে হয়।
উলরিচ শোয়ার্জ


@ শ্যাশন, সত্যই নয়, ক্রন্ড এবং এনএফএসের কথা উল্লেখ করে না।
maxschlepzig

তাই এর সাথে সম্পর্কিত প্রশ্ন: stackoverflow.com/questions/185451/...
maxschlepzig

1
@ অরিচ খুব বিরলভাবে, একটি এনএফএস লকফাইলে একটি পিআইডি সঞ্চয় করে খুব কম মান যুক্ত করে। এমনকি হোস্টনাম যুক্ত করা এখনও লাইভ প্রক্রিয়া যাচাই করতে সত্যই সহায়তা করে না
রোয়াইমা

উত্তর:


45

শেল স্ক্রিপ্টে লকিংয়ের আরও একটি উপায় যা আপনার উপরে বর্ণিত রেসের শর্তটি রোধ করতে পারে, যেখানে দুটি কাজ উভয়ই লাইন 3 পাস করতে পারে The noclobberবিকল্পটি ksh এবং bash এ কাজ করবে। ব্যবহার করবেন না set noclobberকারণ আপনার csh / tcsh এ স্ক্রিপ্ট করা উচিত নয়। ;)

lockfile=/var/tmp/mylock

if ( set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null; then

        trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT

        # do stuff here

        # clean up after yourself, and release your trap
        rm -f "$lockfile"
        trap - INT TERM EXIT
else
        echo "Lock Exists: $lockfile owned by $(cat $lockfile)"
fi

এনএফএসে লকিং সহ ওয়াইএমএমভি (আপনি জানেন, যখন এনএফএস সার্ভারগুলি অ্যাক্সেসযোগ্য নয়) তবে সাধারণভাবে এটি আগের চেয়ে অনেক বেশি শক্তিশালী। (10 বছর আগে)

যদি আপনার ক্রোন জব থাকে যা একাধিক সার্ভার থেকে একই সময়ে একই কাজ করে তবে বাস্তবে চালানোর জন্য আপনার কেবল 1 টি উদাহরণ প্রয়োজন, এর মতো কিছু আপনার পক্ষে কাজ করতে পারে।

লকরুন নিয়ে আমার কোনও অভিজ্ঞতা নেই, তবে স্ক্রিপ্টের আগে চালিত প্রাক-সেট লক পরিবেশটি আসলে চলতে সহায়তা করতে পারে। অথবা এটি নাও পারে। আপনি কেবল নিজের স্ক্রিপ্টের বাইরে লকফিলের জন্য একটি র‍্যাপারে পরীক্ষা নিরীক্ষা করছেন এবং তাত্ত্বিকভাবে, ঠিক একই সময়ে দুটি কাজ লকরুন দ্বারা ডেকে আনা হলে আপনি কেবল একই বর্ণের শর্তটি হিট করতে পারবেন না, ঠিক যেমন 'ভিতরে- 'স্ক্রিপ্ট' সমাধান?

ফাইল লক করা যাই হোক না কেন বেশ সম্মানের সিস্টেমের আচরণ এবং কোনও স্ক্রিপ্ট যা চালানোর আগে লকফিলের অস্তিত্বের জন্য যাচাই করে না তারা যা করবে তা করবে। লকফিল পরীক্ষা এবং সঠিক আচরণের দ্বারা, আপনি যদি 100% না হন তবে 99% সম্ভাব্য সমস্যার সমাধান করবেন।

আপনি যদি অনেকটা লকফাইলে রেসের অবস্থার দিকে চলে যান তবে এটি আপনার বড় কাজগুলির সময়সীমা ঠিক না রাখার মতো বৃহত্তর সমস্যার সূচক হতে পারে, বা যদি কাজ শেষ করার মতো অন্তর খুব গুরুত্বপূর্ণ নাও হতে পারে তবে আপনার কাজটি ডিমনাইজড করার জন্য আরও উপযুক্ত maybe ।


নীচে সম্পাদনা করুন - 2016-05-06 (আপনি যদি কেএসএইচ 88 ব্যবহার করছেন)


নীচে @ ক্লিন্ট পাচেলের মন্তব্যে ভিত্তি করুন, যদি আপনি ksh88 ব্যবহার করেন তবে এর mkdirপরিবর্তে ব্যবহার করুন noclobber। এটি বেশিরভাগ ক্ষেত্রে একটি সম্ভাব্য রেসের শর্তকে হ্রাস করে, তবে এটি পুরোপুরি সীমাবদ্ধ করে না (যদিও ঝুঁকি হ্রাস করা হয়)। আরও তথ্যের জন্য ক্লিন্ট নীচে পোস্ট করা লিঙ্কটি পড়ুন ।

lockdir=/var/tmp/mylock
pidfile=/var/tmp/mylock/pid

if ( mkdir ${lockdir} ) 2> /dev/null; then
        echo $$ > $pidfile
        trap 'rm -rf "$lockdir"; exit $?' INT TERM EXIT
        # do stuff here

        # clean up after yourself, and release your trap
        rm -rf "$lockdir"
        trap - INT TERM EXIT
else
        echo "Lock Exists: $lockdir owned by $(cat $pidfile)"
fi

এবং, একটি অতিরিক্ত সুবিধা হিসাবে, আপনার স্ক্রিপ্টে যদি আপনাকে টেম্পফিলগুলি তৈরি করতে হয়, আপনি lockdirতাদের জন্য ডিরেক্টরিটি ব্যবহার করতে পারেন , তা জেনে স্ক্রিপ্টটি প্রস্থান করার পরে সেগুলি পরিষ্কার করা হবে।

আরও আধুনিক বাশের জন্য, শীর্ষে নোক্লোবার পদ্ধতিটি উপযুক্ত হওয়া উচিত।


1
না, লকরুন দিয়ে আপনার কোনও সমস্যা নেই - যখন কোনও এনএফএস সার্ভার হ্যাং হয়, তখন সমস্ত কলরান কলগুলি কল (অন্তত) lockf()সিস্টেমে কল হবে - যখন এটি ব্যাক আপ হবে তখন সমস্ত প্রক্রিয়া পুনরায় শুরু হবে তবে কেবল একটি প্রক্রিয়াই লকটি জিতবে। কোনও রেসের শর্ত নেই। আমি ক্রোনজবস নিয়ে এ জাতীয় সমস্যায় পড়ি না - বিপরীত ঘটনাটি - তবে এটি এমন সমস্যা যখন আপনাকে আঘাত করে যখন এতে প্রচুর ব্যথা হওয়ার সম্ভাবনা থাকে।
maxschlepzig

1
আমি এই উত্তরটি গ্রহণ করেছি কারণ পদ্ধতিটি নিরাপদ এবং এখন পর্যন্ত সবচেয়ে মার্জিত একটি। আমি একটি ছোট বৈকল্পিকের পরামর্শ দিচ্ছি: set -o noclobber && echo "$$" > "$lockfile"যখন শেল নোক্লোবার বিকল্পটি সমর্থন করে না তখন নিরাপদ ফ্যালব্যাক পেতে to
maxschlepzig

3
উত্তম উত্তর, তবে লকফাইলে থাকা মানটি 'কিল -0' করা উচিত তা নিশ্চিত করতে লক তৈরির প্রক্রিয়াটি এখনও বিদ্যমান রয়েছে তা নিশ্চিত করতে।
নাইজেল হর্ন

1
noclobberবিকল্প অবস্থার জাতি প্রবণ হতে পারে। চিন্তাভাবনার জন্য কিছু খাবারের জন্য mywiki.wooledge.org/BashFAQ/045 দেখুন ।
ক্লিন্ট পাচল

2
দ্রষ্টব্য: ksh88 এ noclobber(বা -C) ব্যবহার করা কাজ করে না কারণ ksh88 এর O_EXCLজন্য ব্যবহার করে না noclobber। আপনি যদি নতুন শেল নিয়ে
চলেছেন তবে

14

আমি হার্ড লিঙ্কগুলি ব্যবহার করতে পছন্দ করি।

lockfile=/var/lock/mylock
tmpfile=${lockfile}.$$
echo $$ > $tmpfile
if ln $tmpfile $lockfile 2>&-; then
    echo locked
else
    echo locked by $(<$lockfile)
    rm $tmpfile
    exit
fi
trap "rm ${tmpfile} ${lockfile}" 0 1 2 3 15
# do what you need to

হার্ড লিঙ্কগুলি এনএফএসের ওপরে পারমাণবিক এবং বেশিরভাগ অংশের জন্য, এমকেডিরও রয়েছে । ব্যবহারিক স্তরে ব্যবহার mkdir(2)বা link(2)প্রায় একইরকম; আমি কেবল শক্ত লিঙ্কগুলি ব্যবহার করতে পছন্দ করি কারণ এনএফএসের আরও বাস্তবায়ন পারমাণবিকের তুলনায় পারমাণবিক হার্ড লিঙ্কগুলিকে অনুমতি দেয় mkdir। এনএফএস-এর আধুনিক প্রকাশের সাথে আপনার কোনওভাবেই উদ্বেগ হওয়ার দরকার নেই।


12

আমি বুঝতে পারছি যে mkdirএটি পারমাণবিক, তাই সম্ভবত:

lockdir=/var/tmp/myapp
if mkdir $lockdir; then
  # this is a new instance, store the pid
  echo $$ > $lockdir/PID
else
  echo Job is already running, pid $(<$lockdir/PID) >&2
  exit 6
fi

# then set traps to cleanup upon script termination 
# ref http://www.shelldorado.com/goodcoding/tempfiles.html
trap 'rm -r "$lockdir" >/dev/null 2>&1' 0
trap "exit 2" 1 2 3 13 15

ঠিক আছে, তবে mkdir()এনএফএসের (> = 3) পারমাণবিক হিসাবে মানক কিনা তা আমি কোনও তথ্য খুঁজে পাইনি ।
ম্যাক্সলেপজিগ 21

2
@ ম্যাক্সচলেপজিগ আরএফসি 1813 স্পষ্টভাবে mkdirপারমাণবিক হওয়ার আহ্বান জানায় না (এটি এর জন্য রয়েছে rename)। বাস্তবে, এটি জানা যায় যে কিছু বাস্তবায়ন হয় না। সম্পর্কিত: জিএনইউ খিলানের লেখকের অবদান সহ একটি আকর্ষণীয় থ্রেড
গিলস

8

একটি সহজ উপায় হ'ল প্যাকেজটি lockfileসহ সাধারণত আসা ব্যবহার করা procmail

LOCKFILE="/tmp/mylockfile.lock"
# try once to get the lock else exit
lockfile -r 0 "$LOCKFILE" || exit 0

# here the actual job

rm -f "$LOCKFILE"

5

semজিএনইউ parallelসরঞ্জামগুলির অংশ হিসাবে আসে যা আপনি যা খুঁজছিলেন তা হতে পারে:

sem [--fg] [--id <id>] [--semaphoretimeout <secs>] [-j <num>] [--wait] command

হিসাবে:

sem --id my_semaphore --fg "echo 1 ; date ; sleep 3" &
sem --id my_semaphore --fg "echo 2 ; date ; sleep 3" &
sem --id my_semaphore --fg "echo 3 ; date ; sleep 3" &

আউটপুট:

1
Thu 10 Nov 00:26:21 UTC 2016
2
Thu 10 Nov 00:26:24 UTC 2016
3
Thu 10 Nov 00:26:28 UTC 2016

মনে রাখবেন যে অর্ডার গ্যারান্টিযুক্ত নয়। এটি শেষ না হওয়া পর্যন্ত আউটপুট প্রদর্শিত হবে না (বিরক্তিকর!)। তবে তবুও, লকফিল এবং পুনরায় চেষ্টা এবং পরিষ্কার-পরিচ্ছন্নতার বিষয়ে চিন্তা না করে, একযোগে সম্পাদনের বিরুদ্ধে রক্ষা করতে আমি সবচেয়ে সংক্ষিপ্ত উপায় way


semহ্যান্ডেল দ্বারা প্রদত্ত লকটি কি মধ্য-মৃত্যুদন্ড কার্যকর করা হবে?
রোয়াইমা

2

আমি ব্যবহার dtach

$ dtach -n /tmp/socket long_running_task ; echo $?
0
$ dtach -n /tmp/socket long_running_task ; echo $?
dtach: /tmp/socket: Address already in use
1

1

আমি এখানে এবং এখানে বর্ণিত হিসাবে আমার বাশ স্ক্রিপ্টগুলিতে লক পরিচালনা করতে কমান্ড-লাইন সরঞ্জাম "ফ্লক" ​​ব্যবহার করি । আমি এই সহজ পদ্ধতিটি ফ্লকের ম্যানপেজ থেকে ব্যবহার করেছি, সাব-শেলটিতে কিছু কমান্ড চালানোর জন্য ...

   (
     flock -n 9
     # ... commands executed under lock ...
   ) 9>/var/lock/mylockfile

উদাহরণস্বরূপ, এটি লকফাইলটি অর্জন করতে না পারলে এটি 1 এর প্রস্থান কোডের সাথে ব্যর্থ হয়। তবে ঝাঁক এমন উপায়ে ব্যবহার করা যেতে পারে যার জন্য সাব-শেল চালানোর জন্য কমান্ডের প্রয়োজন হয় না :-)


3
flock()সিস্টেম কল NFS- র উপর কাজ করে না
maxschlepzig

1
বিএসডির একটি অনুরূপ সরঞ্জাম রয়েছে, "লকফ"।
dubiousjim

2
@ সন্দেহভাজন, বিএসডি লকফ কল করে flock()এবং এনএফএসের মাধ্যমে সমস্যাযুক্ত। বিটিডব্লু, ততক্ষণে, লিনাক্সের ফ্লক () এখন fcntl()ফাইলটি এনএফএস মাউন্টে অবস্থিত যখন ফিরে আসে , সুতরাং, লিনাক্স-কেবল এনএফএস পরিবেশে flock()এখন এনএফএস-এ কাজ করে।
ম্যাক্সলেপজিগ 21

1

একটি ফাইল ব্যবহার করবেন না।

যদি আপনার স্ক্রিপ্টটি এইরূপে কার্যকর করা হয়:

bash my_script

এটি ব্যবহার করে চলছে কিনা তা আপনি সনাক্ত করতে পারেন:

running_proc=$(ps -C bash -o pid=,cmd= | grep my_script);
if [[ "$running_proc" != "$$ bash my_script" ]]; do 
  echo Already locked
  exit 6
fi

এইচএম, পিএস চেকিং কোডটি ভেতর থেকে চলে my_script? ক্ষেত্রে অন্য একটি দৃষ্টান্ত চলছে - running_procদুটি মিলের লাইন থাকে না ? আমি ধারণাটি পছন্দ করি তবে অবশ্যই - অন্য ব্যবহারকারী যখন একই নামে স্ক্রিপ্ট চালাচ্ছেন আপনি মিথ্যা ফলাফল পাবেন ...
ম্যাক্সচলেপজিগ

3
এটিতে একটি বর্ণের শর্তও অন্তর্ভুক্ত রয়েছে: যদি 2 টি উদাহরণ প্রথম পংক্তিকে সমান্তরালভাবে সম্পাদন করে তবে কোনওটি 'লক' পায় না এবং উভয়ই স্থিতি 6 দিয়ে প্রস্থান করে This এটি এক ধরণের পারস্পরিক অনাহার হতে পারে । বিটিডব্লিউ, আমি নিশ্চিত নই আপনি কেন আপনার উদাহরণের $!পরিবর্তে ব্যবহার করেন $$
maxschlepzig

@ ম্যাক্সচলেপজিগ সত্যই ভুল about সম্পর্কে দুঃখিত! বনাম $$
ফ্রগস্টায়ার 78

স্ক্রিপ্টটি পরিচালনা করছে এমন একাধিক ব্যবহারকারীকে পরিচালনা করতে @ ম্যাক্সচ্লেপজিগ ইউজার = -o যুক্তিটিতে যুক্ত করুন।
frogstarr78

@maxschlepzig একাধিক লাইন প্রতিরোধ করতে আপনি আর্গুমেন্টগুলি গ্রেপ বা অতিরিক্ত "ফিল্টার" (উদাঃ grep -v $$) এ পরিবর্তন করতে পারেন । মূলত আমি সমস্যার একটি ভিন্ন পদ্ধতির সরবরাহ করার চেষ্টা করছিলাম।
frogstarr78

1

প্রকৃত ব্যবহারের জন্য, আপনার শীর্ষ ভোট দেওয়া উত্তর ব্যবহার করা উচিত ।

যাইহোক, আমি কিছু ভাঙ্গা এবং অর্ধ-কার্যক্ষম psব্যবহারগুলি এবং তাদের থাকা বহু সতর্কতাগুলি নিয়ে আলোচনা করতে চাই , যেহেতু আমি লোকদের সেগুলি ব্যবহার করতে দেখছি।

এই উত্তরটি আসলে " শেলটিতে লকিং ব্যবহার psgrepপরিচালনা করার জন্য কেন নয় ?" এর উত্তর

ভাঙা পন্থা # 1

প্রথমত, অন্য উত্তরে প্রদত্ত একটি পদ্ধতির যে এটি কার্যকর করে না (এবং কখনই পারে না) এবং পরিষ্কারভাবে কখনও পরীক্ষা করা হয়নি এমন সত্ত্বেও কয়েকটি উত্সাহ রয়েছে:

running_proc=$(ps -C bash -o pid=,cmd= | grep my_script);
if [[ "$running_proc" != "$$ bash my_script" ]]; do 
  echo Already locked
  exit 6
fi

আসুন সিনট্যাক্স ত্রুটিগুলি এবং ভাঙ্গা psযুক্তিগুলি ঠিক করুন এবং পান:

running_proc=$(ps -C bash -o pid,cmd | grep "$0");
echo "$running_proc"
if [[ "$running_proc" != "$$ bash $0" ]]; then
  echo Already locked
  exit 6
fi

এই স্ক্রিপ্টটি সর্বদা 6 থেকে প্রস্থান করা হবে , আপনি এটি যেভাবে চালান তা বিবেচনা করেই।

আপনি যদি এটির সাথে চালনা করেন ./myscriptতবে psআউটপুটটি ঠিক এটি হবে 12345 -bashযা প্রয়োজনীয় স্ট্রিংয়ের সাথে মেলে না 12345 bash ./myscript, তাই এটি ব্যর্থ হবে।

আপনি যদি এটির সাথে চালনা করেন তবে bash myscriptজিনিসগুলি আরও আকর্ষণীয় হয়ে উঠবে। বাশ প্রক্রিয়াটি পাইপলাইনটি চালানোর জন্য কাঁটাচামচ করে, এবং শিশু শেলটি psএবং চালায় grep। আসল শেল এবং চাইল্ড শেল উভয়ই psআউটপুটটিতে প্রদর্শিত হবে, এরকম কিছু:

25793 bash myscript
25795 bash myscript

এটি প্রত্যাশিত আউটপুট নয় $$ bash $0, সুতরাং আপনার স্ক্রিপ্টটি প্রস্থান করবে।

ভাঙা পন্থা # 2

ভাঙা পদ্ধতির # 1 লিখেছেন এমন ব্যবহারকারীদের কাছে এখন সমস্ত ন্যায্যতার সাথে আমি যখন প্রথম চেষ্টা করেছি তখন আমি নিজেই অনুরূপ কিছু করেছি:

if otherpids="$(pgrep -f "$0" | grep -vFx "$$")" ; then
  echo >&2 "There are other copies of the script running; exiting."
  ps >&2 -fq "${otherpids//$'\n'/ }" # -q takes about a tenth the time as -p
  exit 1
fi

এটি প্রায় কাজ করে। তবে পাইপটি চালানোর জন্য দৃking়তার বিষয়টি এটিকে ছুঁড়ে দেয়। সুতরাং এই এক সর্বদা প্রস্থান করবে, এছাড়াও।

অবিশ্বাস্য পদ্ধতির # 3

pids_this_script="$(pgrep -f "$0")"
if not_this_process="$(echo "$pids_this_script" | grep -vFx "$$")"; then
  echo >&2 "There are other copies of this script running; exiting."
  ps -fq "${not_this_process//$'\n'/ }"
  exit 1
fi

এই সংস্করণটি প্রথমে তাদের কমান্ড লাইন আর্গুমেন্টে সমস্ত স্ক্রিপ্ট রয়েছে এমন সমস্ত পিআইডি পেয়ে, এবং তারপরে বর্তমান স্ক্রিপ্টের পিআইডি বাদ দিতে পৃথকভাবে সেই পিডলিস্টটি ফিল্টার করে # 2 পদ্ধতির ক্ষেত্রে পাইপলাইন কাঁটাচামানের সমস্যাটিকে এড়িয়ে চলে ।

এটি কার্যকর হতে পারে ... অন্য কোনও প্রক্রিয়া সরবরাহের সাথে কমান্ড লাইনটি মিলছে না $0, এবং স্ক্রিপ্ট সরবরাহ করার ক্ষেত্রে সর্বদা একইভাবে বলা হয় (যেমন যদি এটি কোনও আপেক্ষিক পথ এবং তারপরে একটি পরম পথের সাথে ডাকা হয়, তবে পরবর্তী উদাহরণটি পূর্ববর্তীটি লক্ষ্য করবে না )।

অবিশ্বাস্য পদ্ধতি # 4

সুতরাং যদি আমরা সম্পূর্ণ কমান্ড লাইনটি পরীক্ষা করা ছেড়ে চলে যাই, যেহেতু এটি সম্ভবত কোনও স্ক্রিপ্ট নির্দেশ করে না, এবং lsofএই স্ক্রিপ্টটি খোলা আছে এমন সমস্ত প্রক্রিয়াগুলি অনুসন্ধান করার জন্য এটি পরীক্ষা করে দেখুন?

ঠিক আছে, হ্যাঁ, এই পদ্ধতিরটি খুব খারাপ নয়:

if otherpids="$(lsof -t "$0" | grep -vFx "$$")"; then
  echo >&2 "Error: There are other processes that have this script open - most likely other copies of the script running.  Exiting to avoid conflicts."
  ps >&2 -fq "${otherpids//$'\n'/ }"
  exit 1
fi

অবশ্যই, যদি স্ক্রিপ্টের অনুলিপিটি চলমান থাকে, তবে নতুন উদাহরণটি ঠিক ঠিক শুরু হবে এবং আপনার দুটি কপি চলবে।

অথবা যদি চলমান স্ক্রিপ্টটি সংশোধন করা হয় (যেমন ভিমের সাথে বা একটি সহ git checkout), তবে স্ক্রিপ্টের "নতুন" সংস্করণটি কোনও সমস্যা ছাড়াই শুরু হবে, যেহেতু ভিম এবং git checkoutফলস্বরূপ উভয়ের পরিবর্তে একটি নতুন ফাইল (একটি নতুন ইনোড) তৈরি হবে পুরোনো একটি.

তবে, যদি স্ক্রিপ্টটি কখনও সংশোধন করা হয় না এবং কখনও অনুলিপি করা হয় না, তবে এই সংস্করণটি বেশ ভাল। কোনও রেসের শর্ত নেই কারণ স্ক্রিপ্ট ফাইলটি চেক পৌঁছানোর আগেই খোলা থাকতে হবে।

অন্য কোনও প্রক্রিয়াটির স্ক্রিপ্ট ফাইল খোলা থাকলেও এখনও মিথ্যা ইতিবাচক থাকতে পারে, তবে নোট করুন যে এটি ভিমে সম্পাদনা করার জন্য উন্মুক্ত থাকলেও, ভিএম আসলে স্ক্রিপ্ট ফাইলটি উন্মুক্ত রাখে না ফলস্বরূপ মিথ্যা ধনাত্মকতার ফল হবে না।

তবে মনে রাখবেন, স্ক্রিপ্টটি সম্পাদনা করা বা অনুলিপি করা হতে পারে যদি আপনি মিথ্যা নেতিবাচক অর্থাত একাধিক দৃষ্টান্ত একসাথে চলতে পারেন তবে এই পদ্ধতির ব্যবহার করবেন না - সুতরাং ভিমের সাথে সম্পাদনা মিথ্যা ধনাত্মক ধরণের ধরণের দেয় না এই বিষয়টি সত্য নয় তোমাকে. আমি এটা উল্লেখ, যদিও কারণ পদ্ধতির # 3 করে মিথ্যা positives দিতে (অর্থাত শুরু করতে রাজি) যদি স্ক্রিপ্টটি তেজ সঙ্গে খোলা আছে।

তাহলে কি করব, তাহলে?

এই প্রশ্নের টপ ভোট উত্তর একটি ভাল কঠিন পদ্ধতির দেয়।

সম্ভবত আপনি আরও ভাল একটি লিখতে পারেন ... তবে উপরের সমস্ত পদ্ধতির সাথে যদি আপনি সমস্ত সমস্যা এবং সতর্কতা বুঝতে না পারেন তবে আপনি লকিং পদ্ধতিটি লিখে ফেলতে পারবেন না যা সেগুলি এড়িয়ে চলে।


0

ব্যবহার FLOM (ফ্রি লক ম্যানেজার) টুল, কমান্ড serializing চলমান মতই সহজ হয়ে

flom -- command_to_serialize

FLOM আপনাকে আরও নমনীয় ব্যবহারের কেসগুলি (বিতরণ লকিং, পাঠক / লেখক, সংখ্যক সংস্থানসমূহ ইত্যাদি) বাস্তবায়িত করার অনুমতি দেয় এখানে যেমন বর্ণিত হয়েছে: http://sourceforge.net/p/flom/wiki/FLOM%20by%20ex উদাহরণ/


0

মেশিনে যে কোনও কাজের জন্য সহজেই রেস শর্তাদি পরিচালনা করতে এমন কোনও বিষয় যা আমি মাঝে মাঝে একটি সার্ভারে যুক্ত করি। এটি টিম কেনেডি-র পোস্টের সাথে সিমিলার, তবে আপনি প্রতিটি প্রতিলিপি স্ক্রিপ্টের জন্য এটির প্রয়োজন কেবল একটি সারি যুক্ত করে রেস পরিচালনা করছেন get

নীচের বিষয়বস্তু যেমন / অপ্ট / রেসচেকার / রেসচেকার রাখুন:

ZPROGRAMNAME=$(readlink -f $0)
EZPROGRAMNAME=`echo $ZPROGRAMNAME | sed 's/\//_/g'`
EZMAIL="/usr/bin/mail"
EZCAT="/bin/cat"

if  [ -n "$EZPROGRAMNAME" ] ;then
        EZPIDFILE=/tmp/$EZPROGRAMNAME.pid
        if [ -e "$EZPIDFILE" ] ;then
                EZPID=$($EZCAT $EZPIDFILE)
                echo "" | $EZMAIL -s "$ZPROGRAMNAME already running with pid $EZPID"  alarms@someemail.com >>/dev/null
                exit -1
        fi
        echo $$ >> $EZPIDFILE
        function finish {
          rm  $EZPIDFILE
        }
        trap finish EXIT
fi

এটি কিভাবে ব্যবহার করবেন তা এখানে। শেবাংয়ের পরে সারিটি নোট করুন:

     #/bin/bash
     . /opt/racechecker/racechecker
     echo "script are running"
     sleep 120

এটি যেভাবে কাজ করে তা হ'ল এটি প্রধান বাশস্ক্রিপ্ট ফাইলটির নামটি খুঁজে বের করে এবং "/ tmp" এর অধীনে একটি পিডফিল তৈরি করে। এটি সমাপ্তি সংকেতে শ্রোতাদেরও যুক্ত করে। মূল স্ক্রিপ্টটি সঠিকভাবে শেষ করা হলে শ্রোতা পিডফিলটি সরিয়ে ফেলবে।

পরিবর্তে যদি কোনও সূচনা চালু করার সময় পিডফিলের উপস্থিতি থাকে, তবে দ্বিতীয় বিবরণটির মধ্যে কোড সম্বলিত if স্টেটমেন্টটি কার্যকর করা হবে। এই ক্ষেত্রে যখন আমি এটি ঘটে তখন একটি অ্যালার্ম মেল চালু করার সিদ্ধান্ত নিয়েছি।

স্ক্রিপ্ট ক্র্যাশ হলে কী হবে

আরও একটি অনুশীলন ক্র্যাশ পরিচালনা করা হবে। মূলত স্ক্রিপ্টটি কোনও কারণেই ক্র্যাশ হয়ে গেলেও, এটি আমার উপরের সংস্করণে করা না হলেও আদর্শভাবে পিডফিলটি সরানো উচিত। এর অর্থ যদি স্ক্রিপ্টটি পিডফিল ক্র্যাশ করে তবে কার্যকারিতা পুনরুদ্ধার করতে ম্যানুয়ালি মুছে ফেলা হবে removed

সিস্টেম ক্রাশের ক্ষেত্রে

পিডফিল / লকফায়াল উদাহরণস্বরূপ / টিএমপি এর অধীনে সংরক্ষণ করা ভাল ধারণা। এইভাবে আপনার স্ক্রিপ্টগুলি অবশ্যই সিস্টেম ক্র্যাশের পরে কার্যকরভাবে চালিয়ে যেতে থাকবে, কারণ পিডফাইলগুলি সর্বদা বুটআপে মুছে ফেলা হবে।


টিম কেনেডি আনসাতজ থেকে পৃথক, আপনার স্ক্রিপ্টে একটি রেসের শর্ত রয়েছে। এটি কারণ আপনার পিআইডিএফআইএল উপস্থিতি এবং এটির শর্তসাপেক্ষ পরীক্ষাটি কোনও পারমাণবিক ক্রিয়াকলাপে করা হয়নি।
maxschlepzig

+1 যে উপর! আমি এটি বিবেচনায় নেব এবং আমার স্ক্রিপ্টটি সংশোধন করব।
জিগস্টার্ডস্ট

-2

আমার স্ক্রিপ্ট পরীক্ষা করুন ...

আপনি পারে ভালোবাসেন এটা ....

[rambabu@Server01 ~]$ sh Prevent_cron-OR-Script_against_parallel_run.sh
Parallel RUN Enabled
Now running
Task completed in Parallel RUN...
[rambabu@Server01 ~]$ cat Prevent_cron-OR-Script_against_parallel_run.sh
#!/bin/bash
#Created by RambabuKella
#Date : 12-12-2013

#LOCK file name
Parallel_RUN="yes"
#Parallel_RUN="no"
PS_GREP=0
LOCK=/var/tmp/mylock_`whoami`_"$0"
#Checking for the process
PS_GREP=`ps -ef |grep "sh $0" |grep -v grep|wc -l`
if [ "$Parallel_RUN" == "no" ] ;then
echo "Parallel RUN Disabled"

 if [ -f $LOCK ] || [ $PS_GREP -gt 2   ] ;then
        echo -e "\nJob is already running OR LOCK file exists. "
        echo -e "\nDetail are : "
        ps -ef |grep  "$0" |grep -v grep
        cat "$LOCK"
  exit 6
 fi
echo -e "LOCK file \" $LOCK \" created on : `date +%F-%H-%M` ." &> $LOCK
# do some work
echo "Now running"
echo "Task completed on with single RUN ..."
#done

rm -v $LOCK 2>/dev/null
exit 0
else

echo "Parallel RUN Enabled"

# do some work
echo "Now running"
echo "Task completed in Parallel RUN..."
#done

exit 0
fi
echo "some thing wrong"
exit 2
[rambabu@Server01 ~]$

-3

'ফ্লকটেস্ট' নামে একটি স্ক্রিপ্টে আমি নিম্নলিখিত সমাধানটি সরবরাহ করি

#!/bin/bash
export LOGFILE=`basename $0`.logfile
logit () {
echo "$1" >>$LOGFILE
}
PROGPATH=$0
(
flock -x -n 257
(($?)) && logit "'$PROGPATH' is already running!" && exit 0
logit "'$PROGPATH', proc($$): sleeping 30 seconds"
sleep 30
)257<$PROGPATH
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.