سؤال تشغيل مهمة كرون يدويا وعلى الفور


(لقد قرأت بالفعل كيف يمكنني اختبار برنامج نصي جديد Cron؟.)

لدي مشكلة محددة (لا يبدو أن مهمة cron قيد التشغيل أو تعمل بشكل صحيح) ، ولكن المشكلة عامة: أود تصحيح البرامج النصية التي يتم حفظها. أدرك أنه يمكنني إعداد خط crontab * * * * * ، لكن هذا ليس حلاً مرضياً تماماً. أود أن أكون قادراً على تشغيل مهمة cron من سطر الأوامر كما لو كانت cron تقوم بتشغيلها (نفس المستخدم ، نفس متغيرات البيئة ، إلخ). هل هناك طريقة للقيام بذلك؟ الحاجة إلى الانتظار 60 ثانية لاختبار تغييرات البرنامج النصي ليست عملية.


94
2017-11-18 13:55


الأصل


(عذرا لا يمكن إضافة تعليق) 0 30 16 20 *؟ * حتى إذا قمت بتشغيل الوظيفة من هذا القبيل ، فإن الفكرة كلها هي توفير إخراج البرنامج النصي لمعرفة ما يحدث خطأ ما لم تكتب الوظيفة إلى سجل ، هذا هو عديم الفائدة للغاية


الأجوبة:


هذا ما فعلته ، ويبدو أنه يعمل في هذه الحالة. على الأقل ، تظهر لي رسالة خطأ ، بينما يتم تشغيلها من سطر الأوامر حيث لا يظهر المستخدم الخطأ.


الخطوة 1: أضع هذا السطر مؤقتًا في crontab المستخدم:

* * * * *   /usr/bin/env > /home/username/tmp/cron-env

ثم اخرجها بمجرد كتابة الملف.

الخطوة 2: صنعت بنصيحة باش قصيرة كتير تحتوي على:

#!/bin/bash
/usr/bin/env -i $(cat /home/username/tmp/cron-env) "$@"

إذن ، كمستخدم في السؤال ، تمكنت من ذلك

run-as-cron /the/problematic/script --with arguments --and parameters

ومن الواضح أن هذا الحل يمكن توسيعه للاستفادة من sudo أو من هذا القبيل لمزيد من المرونة.

آمل أن يساعد هذا الآخرين.


73
2017-11-18 14:40



هذا لا يعمل بالنسبة لي ، وأتساءل عما إذا كان ذلك بالنسبة لأي شخص من upvoted. 1) لماذا تستخدم باش؟ غير مطلوب هنا وقد لا يكون موجودًا في /usr/bin. 2) cat …/cron-env إخراج خطوط متعددة ، وهو لا يعمل. فقط حاول التنفيذ /usr/bin/env -i $(cat cron-env) echo $PATH في المحطة ، فإنه يخرج البيئة حرفيا بدلا من استخدامه. 3) البيئة الحالية يتسرب إلى بيئة cron يحتذى. محاولة: export foo=leaked; run-as-cron echo $foo. - Marco
Marco يعمل في باش ، وهو ما أستخدمه لأنه بيئة أفضل من sh. أستخدم كل شيء من pdksh و ksh (إصدارات متعددة) وباش واندفاع لذلك أنا على دراية كبيرة بالاختلافات بين تطبيقات "الصرفة" من sh ، حتى عند البقاء بصرامة في المجموعة الفرعية المشتركة للغات. :-) - Max Murphy
Marco 2. cat إخراج خطوط متعددة ، والتي تعمل ، لأن استبدال shell ينهار عليها في سطر واحد ، والتي يمكنك التحقق منها echo $(cat cron-env ) | wc. أمر المثال الخاص بك ، /usr/bin/env -i $(cat cron-env) echo $PATHبدائل $PATH من قذيفة الاتصال ؛ بدلاً من ذلك ، يجب أن تستدعي a subshell للاستبدال في subenvironement ، على سبيل المثال. /usr/bin/env -i $(cat cron-env) /bin/sh -c 'echo $PATH'. 3. لقد ارتكبت الخطأ نفسه ، واستبدلت مرة أخرى في shell استدعاء بدلاً من في بيئة فرعية - John Freeman


أقدم حلاً يستند إلى إجابة Pistos ، ولكن بدون العيوب.

  • أضف السطر التالي إلى crontab ، على سبيل المثال ، استخدام crontab -e

    * * * * *  /usr/bin/env > /home/username/cron-env
    
  • قم بإنشاء برنامج نصي shell الذي يقوم بتنفيذ أمر في نفس بيئة تشغيل مهام cron:

    #!/bin/sh
    
    . "$1"
    exec /usr/bin/env -i "$SHELL" -c ". $1; $2"
    

استعمال:

run-as-cron <cron-environment> <command>

مثلا

run-as-cron /home/username/cron-env 'echo $PATH'

لاحظ أن الوسيطة الثانية تحتاج إلى اقتباسها إذا كانت تتطلب وسيطة. يقوم السطر الأول من النص البرمجي بتحميل shell POSIX كمترجم. السطر الثاني هو مصدر ملف بيئة cron. هذا مطلوب لتحميل shell الصحيح الذي تم تخزينه في متغير البيئة SHELL. ثم يقوم بتحميل بيئة فارغة (لمنع تسرب متغيرات البيئة إلى الغلاف الجديد) ، ويطلق نفس الغلاف المستخدم في cronjobs ويحمل متغيرات بيئة cron. أخيرا يتم تنفيذ الأمر.


34
2017-09-24 18:46



هذا ساعدني على إعادة إنتاج خطأ تحميل أبو الهول الخاص بي. - cweiske
لقد استخدمت الخيارreboot cron لكتابة ملف cron-env. يمكنك بعد ذلك تركها في crontab وستتم إعادة كتابتها فقط عند بدء تشغيل النظام. فهو يجعل الأمر أبسط قليلاً حيث لا تضطر إلى إضافة / إزالة الخطوط. - Michael Barton


بما أن crontab لا تقوم بالمهمة ، فستتلاعب بالمحتوى:

crontab -l | grep -v '^#' | cut -f 6- -d ' ' | while read CMD; do eval $CMD; done

ماذا يفعل :

  • يسرد وظائف crontab
  • إزالة خطوط التعليق
  • إزالة التكوين crontab
  • ثم إطلاقها واحدة تلو الأخرى

14
2017-08-19 19:45



هذا لا يعني ذلك بالضرورة في نفس البيئة التي اعتقد فيها cron ، واعتقد انه يريد اختبار واحد منها فقط. - Falcon Momot
صحيح ، لقد تم مخطئا ... فقط تشغيل الوظائف ولكن ليس مثل كرون ستفعل! - Django Janny
لا يزال حل رائع + 1 - Eric Uldall


افتراضيا مع معظم الشياطين cron الافتراضية التي رأيتها ، هناك ببساطة أي طريقة لإبلاغ cron لتشغيل هنا الآن. إذا كنت تستخدم anacron ، فقد يكون من الممكن تشغيل نسخة منفصلة في المقدمة.

إذا لم تكن النصوص البرمجية تعمل بشكل صحيح ، فأنت لا تأخذ ذلك في الاعتبار

  • يتم تشغيل البرنامج النصي كمستخدم معين
  • cron لديه بيئة مقيدة (أكثر مظاهر هذا واضحة هو مسار مختلف).

من crontab (5):

يتم تعيين العديد من متغيرات البيئة   يصل تلقائيا عن طريق كرون (8)   الخفي. يتم تعيين SHELL على / bin / sh و   تم تعيين LOGNAME و HOME من   / etc / passwd line of the crontab   صاحب. يتم تعيين PATH إلى "/ usr / bin: / bin".   قد يكون HOME و SHELL و PATH   تجاوزها الإعدادات في   كرونتاب. LOGNAME هو المستخدم الذي   يتم تشغيل المهمة من ، وربما لا يكون   تغير.

بشكل عام ، تمثل PATH أكبر مشكلة ، لذا تحتاج إلى:

  • قم بوضوح بتعيين PATH داخل البرنامج النصي ، أثناء الاختبار ، إلى / usr / bin: / bin. يمكنك فعل هذا في bash مع تصدير PATH = "/ usr / bin: / bin"
  • قم بوضوح بتعيين PATH الصحيح الذي تريده في الجزء العلوي من crontab. مثلا PATH = "/ البيرة / بن: / بن: / البيرة / المحلية / بن: / البيرة / دليل: / دليل"

إذا كنت بحاجة إلى تشغيل البرنامج النصي كمستخدم آخر بدون shell (مثل www-data) ، فاستخدم sudo:

sudo -u www-data /path/to/crontab-script.sh

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


5
2017-11-18 14:27



شكرا لك على الرد الكامل. أنا على علم بموضوعي التشغيل كمستخدم معين ، ومع بيئة معينة. على هذا النحو ، قمت بصياغة إجابتي الخاصة ، والتي سأقوم بنشرها الآن ... - Pistos
تعتبر أحرف الهروب من الأسباب الصحيحة لعدم تشغيل الوظيفة - Joe Phillips


حسنا ، المستخدم هو نفسه الذي وضعته في مدخل crontab (أو الذي وضعته crontab في ، بالتناوب) ، لذلك هذا هو عدم التفكير. crontab(5) يجب أن يعطيك قائمة متغيرات البيئة المحددة ، هناك عدد قليل فقط.


1
2017-11-18 14:04



وبعبارة أخرى ، أنت تقول أنه لا توجد طريقة للقيام بذلك؟ فقط "قريبة بما فيه الكفاية" من الحلول؟ - Pistos
لا ، أنا أقول أنه يمكنك القيام بذلك ، وذلك باستخدام المعلومات التي قدمتها في إجابتي. - womble♦


في معظم crontabs مثل e.g. vixie-cron يمكنك وضع المتغيرات في crontab نفسه على هذا النحو ثم استخدام / usr / bin / env للتحقق مما إذا كان يعمل. وبهذه الطريقة يمكنك جعل النص الخاص بك يعمل في crontab بمجرد اكتشاف ما الخطأ في البرنامج النصي run-as-cron.

SHELL=/bin/bash
LANG=en
FASEL=BLA

* * * * *   /usr/bin/env > /home/username/cron-env

1
2017-10-27 06:52





لم يعمل نص ماركو بالنسبة لي لسبب ما. لم يكن لدي متسع من الوقت لتصحيح الأخطاء ، لذلك كتبت نصًا بيثيًا به نفس الشيء. إنها أطول ، ولكن: أولاً ، إنها تعمل بالنسبة لي ، وثانياً ، أجد أنه من الأسهل فهمها. غيّر "/ tmp / cron-env" إلى المكان الذي حفظت فيه بيئتك. ها هو:

#!/usr/bin/env python
from __future__ import division, print_function

import sys
import os

def main():
    if len(sys.argv) != 2 or sys.argv[1] in ('-h', '--help'):
        print("Usage: {} CMD\n"
              "Run a command as cron would. Note that CMD must be quoted to be only one argument."
              .format(sys.argv[0]))
        sys.exit(1)
    _me, cmd = sys.argv
    env = dict(line.strip().split('=', 1) for line in open('/tmp/cron-env'))
    sh = env['SHELL']
    os.execvpe(sh, [sh, '-c', cmd], env)

if __name__ == '__main__':
    main()

1
2017-12-24 08:48





لم يعمل حل ماركو بالنسبة لي ، لكن مخطوطة بيثون ناعام عملت. هنا تعديل طفيف على نص ماركو الذي جعله يعمل لي:

#!/bin/sh
. "$1"
exec /usr/bin/env -i "$SHELL" -c "set -a;. $1; $2"

وأضاف set -a متغيرات التصدير المعرفة بالبرنامج النصي $ 1 وجعلها متاحة لقيادة $ 2

ملاحظة عملت بيثون Noam لكونها 'تصدير' البيئة لعملية الطفل.


1
2018-05-11 05:05