سؤال منع تكرار كرون وظائف قيد التشغيل


لقد قمت بجدولة مهمة كرون لتشغيل كل دقيقة ، لكن في بعض الأحيان يستغرق البرنامج النصي أكثر من دقيقة للانتهاء ولا أريد أن تبدأ الوظائف في "تكديس" فوق بعضها البعض. أعتقد أن هذه مشكلة التزامن - بمعنى أن تنفيذ البرنامج النصي يجب أن يكون حصريًا.

لحل المشكلة ، نظرت في البرنامج النصي لوجود ملف معين ("lockfile.txt") والخروج إذا كان موجودًا أو touch إذا لم يحدث ذلك. ولكن هذا هو إشارة سيئة رديئة جدا! هل هناك أفضل الممارسات التي يجب أن أعرفها؟ يجب أن كنت قد كتبت خفي بدلا من ذلك؟


81
2017-11-09 11:32


الأصل




الأجوبة:


هناك برنامجان يعملان على أتمتة هذه الميزة ، ويزيلان الإزعاج والحشرات المحتملة من القيام بذلك بنفسك ، وتجنب مشكلة القفل البائس عن طريق استخدام القطيع خلف الكواليس أيضًا (وهو خطر إذا كنت تستخدم اللمس فقط) . لقد استعملت lockrun و lckdo في الماضي ، ولكن الآن هناك flock(1) (في إصدارات جديدة من util-linux) وهو أمر رائع. انها حقا سهلة الاستعمال:

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

109
2017-11-09 11:57



سوف يتم إزالة lckdo من moreutils ، الآن أن قطيع (1) في استخدام لينكس. وتلك الحزمة ضرورية بشكل أساسي في أنظمة Linux ، لذا يجب أن تكون قادرًا على الاعتماد على وجودها. للاستخدام ، انظر أدناه. - jldugger
نعم ، أصبح قطيع الخيار المفضل الآن. سوف أقوم بتحديث إجابتي لرفع الدعوى. - womble♦
هل يعرف أحد الفرق بين flock -n file command و flock -n file -c command ؟ - Nanne
Nanne ، يجب أن أتحقق من الشفرة للتأكد ، لكن تخميني هو ذلك -c يدير الأمر المحدد من خلال قذيفة (كما هو الحال في manpage) ، في حين أن "عارية" (غير-c) شكل فقط execق الأمر المعطى. يسمح لك وضع شيء ما عبر القشرة بعمل أشياء تشبه القشرة (مثل تشغيل أوامر متعددة مفصولة ; أو &&) ، ولكن أيضًا يفتح لك إمكانية توسيع هجمات التوسع إذا كنت تستخدم إدخالًا غير موثوق به. - womble♦
كان حجة إلى (افتراضية) frequent_cron_job الأمر الذي حاول إظهار أنه يتم تشغيله كل دقيقة. لقد أزلته لأنه لم يضف شيئًا مفيدًا ، وتسبب في حدوث ارتباك (لك ، إذا لم يكن أي شخص آخر على مر السنين). - womble♦


أفضل طريقة في شل هو استخدام قطيع (1)

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

27
2017-11-09 11:45



لا أستطيع أن أحصل على استخدام خادع لإعادة توجيه fd. انها مجرد فظيع جدا. - womble♦
لا تحليل بالنسبة لي في باش أو ZSH ، تحتاج إلى القضاء على المسافة بين 99 و > اذا هي كذلك 99> /... - Kyle Brandt♦
Javier: لا يعني أنها ليست خادعة وغامضة ، بل إنها كذلك موثقوصعب وغامض. - womble♦
ماذا سيحدث إذا قمت بإعادة تشغيل أثناء تشغيل هذا أو الحصول على عملية قتل بطريقة أو بأخرى؟ هل ستكون مغلقة إلى الأبد؟ - Alex R
أنا أفهم أن هذا الهيكل يخلق قفلًا حصريًا لكنني لا أفهم آليات كيفية تحقيق ذلك. ما وظيفة "99" في هذه الإجابة؟ أي شخص يهتم بشرح هذا من فضلك؟ شكر! - Asciiom


في الواقع، flock -n يمكن استخدامها بدلا من lckdo* ، لذلك سوف تستخدم رمز من مطوري النواة.

بناء على مثال womble، تكتب شيئًا مثل:

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

راجع للشغل ، وتبحث في رمز ، كل من flock، lockrunو lckdo افعل نفس الشيء بالضبط ، لذلك فالأمر هو الأكثر ملاءمة لك.

* نظرًا لأنه في ضوء سمعتي في وقت كتابة هذا التقرير ، لا يمكنني تحرير أو التعليق على الإجابات السابقة ، لا بد لي من كتابة هذا كإجابة منفصلة.


21
2017-11-19 22:43





يمكنك استخدام ملف القفل. قم بإنشاء هذا الملف عند بدء تشغيل البرنامج النصي وحذفه عند الانتهاء. يجب أن يتحقق البرنامج النصي ، قبل تشغيله روتينه الرئيسي ، إذا كان ملف القفل موجودًا ومتابعة وفقًا لذلك.

يتم استخدام Lockfiles بواسطة initscripts والعديد من التطبيقات والأدوات المساعدة الأخرى في أنظمة Unix.


2
2017-11-09 11:36



هذا ال فقط طريقة رأيته نفذت ، شخصيا. أستخدمها حسب اقتراح المشرف كمرآة لمشروع OSS - warren


قد يكون هذا أيضًا علامة على أنك تفعل الخطأ. إذا كانت مهامك تعمل عن كثب وبشكل متكرر ، فربما ينبغي عليك التفكير في إلغاء ذلك وجعله برنامجًا شبيهًا بالألعاب.


1
2017-11-09 11:45



أنا أختلف بحرارة مع هذا. إذا كان لديك شيء يحتاج إلى تشغيله بشكل دوري ، فإن جعله خفي هو "مطرقة للجوز". إن استخدام lockfile لمنع الحوادث هو حل معقول تمامًا لم أواجه مشكلة في استخدامه. - womble♦
womble أوافق ؛ لكني أحب تحطيم المكسرات بمقاومتها! :-) - wzzrd


لقد حددت ما إذا كنت تريد أن ينتظر البرنامج النصي حتى يكتمل التشغيل السابق أم لا. من خلال "لا أريد أن تبدأ المهام" بتكديس "فوق بعضها البعض" ، أعتقد أنك تشير إلى أنك تريد إنهاء البرنامج النصي إذا كان قيد التشغيل بالفعل ،

لذا ، إذا كنت لا ترغب في الاعتماد على 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
2017-11-09 14:33



شكرًا جزيلاً مفيدًا - أرغب في خروج البرنامج النصي إذا كان قيد التشغيل بالفعل. شكرا على ذكر ذلك ickdo - يبدوا انها تكفي للخدعه. - Tom


لا ينبغي أن يستدعي برنامج cron daemon وظائفك إذا كانت النسخ السابقة منها لا تزال قيد التشغيل. أنا مطور لبرنامج cron واحد dcronونحاول على وجه التحديد منع ذلك. لا أعرف كيف يتعامل فيكسى كرون أو الشياطين الأخرى مع هذا.


1
2018-02-17 15:59