ডুপ্লিকেট ক্রোন কাজ চলমান রোধ করুন


92

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

সমস্যা সমাধানের জন্য আমি স্ক্রিপ্টটিকে একটি নির্দিষ্ট ফাইল (" লকফিল.টেক্সট ") এর অস্তিত্বের সন্ধান করেছি এবং এটি উপস্থিত থাকলে বা touchযদি তা না থাকে তবে প্রস্থান করুন । তবে এটি একটি সুন্দর লম্পট সেমফোর! আমার সম্পর্কে জানা উচিত এমন একটি সর্বোত্তম অনুশীলন কি আছে? এর বদলে আমার কি ডেমোন লেখা উচিত ছিল?

উত্তর:


118

বেশ কয়েকটি প্রোগ্রাম রয়েছে যা এই বৈশিষ্ট্যটিকে স্বয়ংক্রিয় করে তোলে, বিরক্তি এবং সম্ভাব্য বাগগুলি নিজেই করা থেকে দূরে সরিয়ে দেয় এবং পর্দার পিছনে ঝাঁক ব্যবহার করে বাসি লক সমস্যাটি এড়ানোও হয় (যদি আপনি কেবল স্পর্শ ব্যবহার করেন তবে এটি ঝুঁকিপূর্ণ) । আমি ব্যবহার করেছি lockrunএবং lckdoঅতীতেও ছিলাম , তবে এখন flock(1) (ইউজার-লিনাক্সের নতুন সংস্করণে) রয়েছে যা দুর্দান্ত। এটি ব্যবহার করা সত্যই সহজ:

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job

2
lckdo আরও ব্যবহার্য পদার্থ থেকে সরানো হবে, এখন যে ঝাঁক (1) ইউজার-লিনাক্সে রয়েছে। এবং সেই প্যাকেজটি মূলত লিনাক্স সিস্টেমে বাধ্যতামূলক, সুতরাং আপনার উপস্থিতির উপর নির্ভর করতে সক্ষম হওয়া উচিত। ব্যবহারের জন্য, নীচে দেখুন।
jldugger

হ্যাঁ, পাল এখন আমার পছন্দের বিকল্প। আমি আমার উত্তর স্যুট আপডেট করব।
ভোমল

যে কেউ এর মধ্যে পার্থক্য কি জানে flock -n file commandএবং flock -n file -c command?
Nanne

2
@ ন্যান, আমাকে নিশ্চিত হওয়ার জন্য কোডটি পরীক্ষা করতে হবে, তবে আমার শিক্ষিত অনুমানটি -cশেল (ম্যানপেজ অনুসারে) দ্বারা নির্দিষ্ট কমান্ডটি চালায়, যখন "খালি" (নন- -c) ফর্মটি কেবলমাত্র execপ্রদত্ত আদেশটি সরিয়ে দেয় । শেলের মাধ্যমে কিছু দেওয়া আপনাকে শেলের মতো জিনিসগুলি করতে দেয় (যেমন একাধিক কমান্ড ;বা এর দ্বারা পৃথক পৃথকভাবে চালানো &&), তবে আপনি যদি অবিশ্বস্ত ইনপুট ব্যবহার করেন তবে শেল এক্সপেনশন আক্রমণেও আপনাকে উন্মুক্ত করে।
দোলা

1
এটি (অনুমানমূলক) frequent_cron_jobকমান্ডের একটি যুক্তি যা দেখানোর চেষ্টা করেছিল যে প্রতি মিনিটে এটি চালানো হচ্ছে। আমি এটিকে অপসারণ করেছি কারণ এটি কোনও কার্যকর কিছু যোগ করেনি এবং বিভ্রান্তি সৃষ্টি করেছে (আপনার, যদি বছরের পর বছর ধরে কেউ না থাকে)।
womble

28

শেলের সর্বোত্তম উপায় হ'ল পাল (1)

(
  flock -x -w 5 99
  ## Do your stuff here
) 99>/path/to/my.lock

1
আমি এফডি পুনঃনির্দেশের একটি কৌতূহলপূর্ণ ব্যবহারকে উচ্চারণ করতে পারি না। এটা ঠিক খুব arcanely দুর্দান্ত।
দোলা

1
বাশ বা জেডএসএইচে আমার জন্য বিশ্লেষণ করবেন না, এর মধ্যে স্থানটি সরিয়ে ফেলতে হবে 99এবং >তাই এটি99> /...
কাইল ব্র্যান্ড্ট

2
@ জাভিয়ার: এর অর্থ এই নয় যে এটি কৌতুকপূর্ণ এবং আরকেন নয়, কেবল এটি ডকুমেন্টেড , কৌতুকপূর্ণ এবং আরকেন।
দোলা

1
এই চলমান অবস্থায় আপনি যদি পুনরায় চালু করেন বা প্রক্রিয়াটি কোনওভাবে মারা যায় তবে কী হবে? এটা কি চিরতরে লক হয়ে থাকবে?
অ্যালেক্স

5
আমি বুঝতে পারি এই কাঠামোটি একচেটিয়া লক তৈরি করে তবে কীভাবে এটি সম্পন্ন হয় তার যান্ত্রিকতা আমি বুঝতে পারি না। এই উত্তরের '99' এর কাজটি কী? কেউ দয়া করে এই ব্যাখ্যা করতে যত্নশীল? ধন্যবাদ!
Asciiom

22

আসলে, * এর flock -nপরিবর্তে ব্যবহার করা যেতে পারে lckdo, তাই আপনি কার্নেল বিকাশকারীদের কোড ব্যবহার করবেন।

উপর নির্মাণের womble উদাহরণ , আপনি ভালো কিছু লিখতে হবে:

* * * * * flock -n /some/lockfile command_to_run_every_minute

BTW, এর সমস্ত কোড দিকে তাকিয়ে flock, lockrunআর lckdoসঠিক একই জিনিস, তাই এটি শুধু একটি ব্যাপার যার বেশিরভাগ নির্দ্ধিধায় আপনার জন্য উপলব্ধ আছে।


2

আপনি একটি লক ফাইল ব্যবহার করতে পারেন। স্ক্রিপ্ট শুরু হওয়ার সাথে সাথে এই ফাইলটি তৈরি করুন এবং এটি শেষ হয়ে গেলে মুছুন। স্ক্রিপ্টটি এর প্রধান রুটিন চালানোর আগে লক ফাইলটি উপস্থিত রয়েছে কিনা তা পরীক্ষা করা উচিত এবং সেই অনুযায়ী অগ্রসর হওয়া উচিত।

লকফিলগুলি ইউনিক্স সিস্টেমে ইনসক্রিপ্ট এবং আরও অনেক অ্যাপ্লিকেশন এবং ইউটিলিটি দ্বারা ব্যবহৃত হয়।


1
এটি কেবলমাত্র আমি কখনও ব্যক্তিগতভাবে এটি প্রয়োগ করে দেখেছি। আমি ওএসএস প্রকল্পের জন্য আয়না হিসাবে রক্ষণাবেক্ষণকারীর পরামর্শ অনুযায়ী ব্যবহার করি
ওয়ারেন

2

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

সুতরাং, আপনি যদি lckdo বা অনুরূপ উপর নির্ভর করতে চান না, আপনি এটি করতে পারেন:


PIDFILE=/tmp/`basename $0`.pid

if [ -f $PIDFILE ]; then
  if ps -p `cat $PIDFILE` > /dev/null 2>&1; then
      echo "$0 already running!"
      exit
  fi
fi
echo $$ > $PIDFILE

trap 'rm -f "$PIDFILE" >/dev/null 2>&1' EXIT HUP KILL INT QUIT TERM

# do the work


ধন্যবাদ আপনার উদাহরণ সহায়ক - আমি ইতিমধ্যে চলমান থাকলে স্ক্রিপ্টটি প্রস্থান করতে চাই। আকদো উল্লেখ করার জন্য ধন্যবাদ - এটি কৌশলটি মনে হচ্ছে।
টম

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

1

এটি কোনও চিহ্ন হতে পারে যে আপনি ভুল কাজটি করছেন। যদি আপনার কাজগুলি ঘনিষ্ঠভাবে এবং এটি প্রায়শই চালিত হয় তবে সম্ভবত আপনি এটি ডি-ক্রোন করা এবং এটি একটি ডেমন-শৈলীর প্রোগ্রাম হিসাবে বিবেচনা করা উচিত।


3
আমি আন্তরিকভাবে এই সাথে একমত। আপনার যদি পর্যায়ক্রমে চালনার দরকার এমন কিছু কিছু থাকে তবে এটিকে ডেমন বানানো একটি "বাদামের জন্য স্লেজহ্যামার" সমাধান। দুর্ঘটনা রোধ করতে লকফিল ব্যবহার করা একদম যুক্তিসঙ্গত সমাধান যা আমি ব্যবহার করতে কখনও সমস্যা হয়নি।
দোলা

@ ওম্বল আমি সম্মত; তবে আমি স্লেজহ্যামারদের সাথে বাদাম ছিটিয়ে দেওয়া পছন্দ করি! :-)
wzzrd

1

যদি আপনার পূর্ববর্তী দৃষ্টান্তগুলি এখনও চলমান থাকে তবে আপনার ক্রোন ডেমনটি চাকরীর জন্য অনুরোধ করা উচিত নয়। আমি একটি ক্রোন ডেমন ডক্রনের বিকাশকারী এবং আমরা এটি প্রতিরোধ করার জন্য বিশেষত চেষ্টা করি। আমি জানি না ভিক্সি ক্রোন বা অন্যান্য ডেমন এটি কীভাবে পরিচালনা করে।


1

আমি রান-ওয়ান কমান্ডটি ব্যবহারের পরামর্শ দেব - লকগুলির সাথে ডিল করার চেয়ে অনেক সহজ। দস্তাবেজগুলি থেকে:

রান-ওয়ান একটি মোড়ক স্ক্রিপ্ট যা আর্গুমেন্টের একটি অনন্য সেট সহ কিছু কমান্ডের একের বেশি অনন্য ঘটনা চালায় না। আপনি যখন একবারে একাধিক অনুলিপি না চান তখন এটি ক্রোনজবসগুলিতে প্রায়শই কার্যকর।

রান-এই-ওয়ান হ'ল রান-এর মতো, এটি ব্যবহারকারীর মালিকানাধীন যে কোনও চলমান প্রক্রিয়া এবং লক্ষ্য কমান্ড এবং যুক্তিগুলির সাথে মিলে যাবার জন্য এবং pgrep ব্যবহার করে ব্যবহার করবে except মনে রাখবেন যে সমস্ত ম্যাচিং প্রক্রিয়া শেষ না হওয়া অবধি ম্যাচিং প্রসেসগুলি মারার চেষ্টা করার সময় এই-রোধটি অবরুদ্ধ হবে।

রান-ও-ধারাবাহিকভাবে রান-ওনের মতোই চালিত হয় তা ছাড়া এটি যে কোনও সময় কম্যান্ড থেকে বেরিয়ে আসে (শূন্য বা শূন্য নয়) "COMMAND [ARGS]" কে সম্মতি দেয়।

কিপ-ওয়ান-রানিং ক্রমাগত রান ওয়ান-র জন্য একটি উপাধি।

রান-ওন-টু-সাফল্য ঠিক রান-ও-ধীরে ধীরে চালিত হয় কেবল ব্যতীত এটি "কম্যান্ড [আর্গস]" সাফল্য দেয় যতক্ষণ না কম্যান্ড সফলভাবে প্রস্থান না করে (অর্থাৎ শূন্য থেকে বেরিয়ে যায়)।

রান-ওয়ান-অব-ব্যর্থতা রান-ও-অবিচ্ছিন্নভাবে ঠিক একইভাবে কাজ করে except ব্যতীত যখন কম্যান্ড ব্যর্থতার সাথে প্রস্থান না করে (অর্থাৎ শূন্যহীন থেকে বেরিয়ে যায়) যতক্ষণ না এটি "কম্যান্ড [আরজিএস]" রোধ করে।


1

এখন সিস্টেমড আউট হয়ে গেছে, লিনাক্স সিস্টেমে অন্য সময়সূচী প্রক্রিয়া রয়েছে:

একজন systemd.timer

ইন /etc/systemd/system/myjob.serviceবা ~/.config/systemd/user/myjob.service:

[Service]
ExecStart=/usr/local/bin/myjob

ইন /etc/systemd/system/myjob.timerবা ~/.config/systemd/user/myjob.timer:

[Timer]
OnCalendar=minutely

[Install]
WantedBy=timers.target

টাইমার পরবর্তীটি সক্রিয় হওয়ার পরে যদি পরিষেবা ইউনিট ইতিমধ্যে সক্রিয় হয় তবে পরিষেবাটির আর একটি উদাহরণ শুরু হবে না

একটি বিকল্প, যা বুটে একবার কাজ শুরু করে এবং প্রতিটি রান শেষ হওয়ার এক মিনিট পরে:

[Timer]
OnBootSec=1m
OnUnitInactiveSec=1m 

[Install]
WantedBy=timers.target

0

এই জাতীয় সমস্যা সমাধানের জন্য আমি একটি জার তৈরি করেছি যেমন নকল ক্রোনগুলি চলছে জাভা বা শেল ক্রোন। ডুপ্লিকেটগুলিতে কেবল ক্রোন নামটি পাস করুন loক্লসসেশনস ("ডেমো.জার") এটি বর্তমান ছাড়াও এই ক্রোনটির জন্য অস্তিত্বের পিড অনুসন্ধান এবং হত্যা করবে। আমি এই জিনিসটি করার পদ্ধতি প্রয়োগ করেছি। স্ট্রিং সর্বনাম = পরিচালনা স্ট্রিং পিড = সর্বনাম.স্প্লিট ("@") [0]; System.out.println ("বর্তমান পিআইডি:" + পিড);

            Process proc = Runtime.getRuntime().exec(new String[]{"bash","-c"," ps aux | grep "+cronname+" | awk '{print $2}' "});

            BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String s = null;
            String killid="";

            while ((s = stdInput.readLine()) != null ) {                                        
                if(s.equals(pid)==false)
                {
                    killid=killid+s+" ";    
                }
            }

এবং তারপরে আবার শেল কমান্ড দিয়ে কিলিড স্ট্রিং কিল করুন


আমি মনে করি না এটি সত্যই প্রশ্নের উত্তর দিচ্ছে।
ক্যাস্পারড

0

@ ফিলিপ রেনল্ডস উত্তরটি লক না পেয়ে যেকোনোভাবে 5s অপেক্ষা সময়ের পরে কোডটি কার্যকর করা শুরু করবে। অনুসরণ করছেন ফ্লক কাজ করা বলে মনে হচ্ছে না আমি @Philip রেনল্ডস উত্তর পরিবর্তিত

(
  flock -w 5 -x 99 || exit 1
  ## Do your stuff here
) 99>/path/to/my.lock

যাতে কোডটি কখনই একযোগে কার্যকর করা না যায়। পরিবর্তে 5 সেকেন্ড অপেক্ষা করার পরে প্রক্রিয়াটি 1 দিয়ে প্রস্থান করবে যদি ততক্ষণে এটি লকটি না পেয়ে থাকে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.