जाँच करें कि स्क्रिप्ट क्रोन द्वारा शुरू की गई है, बजाय मैन्युअल रूप से आह्वान किए


23

क्या कोई चर है जो क्रोन सेट करता है जब वह एक प्रोग्राम चलाता है? यदि स्क्रिप्ट क्रोन द्वारा चलाई जाती है, तो मैं कुछ हिस्सों को छोड़ना चाहूंगा; अन्यथा उन भागों का आह्वान करें।

मुझे कैसे पता चल सकता है कि बैश स्क्रिप्ट क्रोन द्वारा शुरू की गई है?


तुम सिर्फ हमें क्यों नहीं ps?
terdon


@terdon: शायद इसलिए psकि काफी बुरी तरह से प्रलेखित किया गया है (विशेष रूप से लिनक्स का संस्करण जो कई अलग-अलग वाक्यविन्यास शैलियों का समर्थन करता है) और मैन पेज अधिकांश टूलों की तुलना में अधिक घना और गूढ़ है। मुझे संदेह है कि ज्यादातर लोगों को यह भी एहसास नहीं है कि एक उपकरण कितना उपयोगी और बहुमुखी psहो सकता है।
कैस

जवाबों:


31

मुझे पता नहीं है कि cronडिफ़ॉल्ट रूप से इसके पर्यावरण के लिए कुछ भी किया जाता है जो यहां उपयोग किया जा सकता है, लेकिन कुछ चीजें हैं जो आप वांछित प्रभाव प्राप्त करने के लिए कर सकते हैं।

1) स्क्रिप्ट फ़ाइल के लिए एक हार्ड या सॉफ्ट लिंक बनाएं, ताकि, उदाहरण के लिए, myscriptऔर myscript_via_cronउसी फ़ाइल को इंगित करें। आप तब $0स्क्रिप्ट के अंदर के मूल्य का परीक्षण कर सकते हैं जब आप कोड के कुछ हिस्सों को सशर्त रूप से चलाना या छोड़ना चाहते हैं। उपयुक्त नाम अपने कॉन्टैब में रखें, और आप सेट हैं।

2) स्क्रिप्ट में एक विकल्प जोड़ें, और उस विकल्प को क्रोस्टैब मंगलाचरण में सेट करें। उदाहरण के लिए, एक विकल्प जोड़ें -c, जो स्क्रिप्ट को कोड के उपयुक्त भागों को चलाने या छोड़ने के लिए कहता है, और -cअपने क्रॉस्टैब में कमांड नाम जोड़ें ।

और निश्चित रूप से, क्रोन मनमाने ढंग से पर्यावरण चर सेट कर सकते हैं , इसलिए आप बस RUN_BY_CRON="TRUE"अपने कॉन्टैब की तरह एक लाइन डाल सकते हैं , और अपनी स्क्रिप्ट में इसके मूल्य की जांच कर सकते हैं।


7
RUN_BY_CRON के लिए +1 = सच
कैस

कैस द्वारा जवाब बहुत अच्छी तरह से काम कर रहा है और इसे किसी और चीज के लिए भी इस्तेमाल किया जा सकता है
डियान

19

क्रोन से चलने वाले लिपियों को संवादात्मक गोले में नहीं चलाया जाता है। न ही स्टार्टअप स्क्रिप्ट हैं। भेदभाव यह है कि इंटरेक्टिव गोले में STDIN और STDOUT एक ट्टी से जुड़ा होता है।

विधि 1: जाँचें कि क्या झंडा $-शामिल है iiइंटरैक्टिव गोले के लिए निर्धारित है।

case "$-" in
    *i*)
        interactive=1
        ;;
    *)
        not_interactive=1
        ;;
esac

विधि 2: चेक $PS1खाली है।

if [ -z "$PS1" ]; then
    not_interactive=1 
else
    interactive=1
fi

संदर्भ: http://techdoc.kvindesland.no/linux/gnubooks/bash/bashref_.html

विधि 3: अपने tty का परीक्षण करें। यह उतना विश्वसनीय नहीं है , लेकिन सरल क्रोन नौकरियों के लिए आपको ठीक होना चाहिए, क्योंकि क्रोन डिफ़ॉल्ट रूप से एक स्क्रिप्ट को एक ट्टी आवंटित नहीं करता है।

if [ -t 0 ]; then
    interactive=1
else
    non_interactive=1
fi

ध्यान रखें कि आप एक इंटरैक्टिव शेल का उपयोग करने के लिए बाध्य कर सकते हैं -i, लेकिन आप शायद जानते होंगे कि क्या आप ऐसा कर रहे थे ...


1
ध्यान दें कि स्क्रिप्ट की शुरुआत सिस्टम द्वारा की जाती है या नहीं, यह जांचने पर $ PS1 कमांड काम नहीं करता है। $ - एक करता है
mveroone

1
आपका विन्निपेग विश्वविद्यालय लिंक टूट गया है।
WinEunuuchs2Unix

1
आप @TimKennedy स्वागत है .... एडमोंटन से :)
WinEunuuchs2Unix

"केस" $ - "इन बैश स्क्रिप्ट में काम नहीं करता है।
होबडे

@Hobadee - हर bashएक के पास $ का उपयोग होता है - जैसा कि करना dashऔर ksh। यहां तक ​​कि सोलारिस में प्रतिबंधित गोले भी हैं। आप इसे किस प्लेटफ़ॉर्म पर उपयोग करने का प्रयास कर रहे हैं, जहां यह काम नहीं कर रहा है क्या case "$-" in *i*) echo true ;; *) echo false ;; esacदिखाता है आपको?
टिम केनेडी

7

सबसे पहले, क्रोन की पीआईडी ​​प्राप्त करें, फिर वर्तमान प्रक्रिया के जनक पीआईडी ​​(पीपीआईडी) प्राप्त करें, और उनकी तुलना करें:

CRONPID=$(ps ho %p -C cron)
PPID=$(ps ho %P -p $$)
if [ $CRONPID -eq $PPID ] ; then echo Cron is our parent. ; fi

यदि आपकी स्क्रिप्ट किसी अन्य प्रक्रिया द्वारा शुरू की गई है, जो क्रोन द्वारा शुरू की गई हो सकती है, तो आप पैरेंट पीआईडी ​​को अपना रास्ता बना सकते हैं, जब तक कि आप $ CRONPID या 1 (init का PID) प्राप्त न कर लें।

कुछ इस तरह से, शायद (अनटाइटेड-बट-इट-माइट-वर्क <टीएम>):

PPID=$$   # start from current PID
CRON_IS_PARENT=0
CRONPID=$(ps ho %p -C cron)
while [ $CRON_IS_PARENT -ne 1 ] && [ $PPID -ne 1 ] ; do
  PPID=$(ps ho %P -p $PPID)
  [ $CRONPID -eq $PPID ] && CRON_IS_PARENT=1
done

डेयान से: यह रेडहैट लिनक्स पर परीक्षण किया गया एक संस्करण है

# start from current PID
MYPID=$$
CRON_IS_PARENT=0
# this might return a list of multiple PIDs
CRONPIDS=$(ps ho %p -C crond)

CPID=$MYPID
while [ $CRON_IS_PARENT -ne 1 ] && [ $CPID -ne 1 ] ; do
        CPID_STR=$(ps ho %P -p $CPID)
        # the ParentPID came up as a string with leading spaces
        # this will convert it to int
        CPID=$(($CPID_STR))
        # now loop the CRON PIDs and compare them with the CPID
        for CRONPID in $CRONPIDS ; do
                [ $CRONPID -eq $CPID ] && CRON_IS_PARENT=1
                # we could leave earlier but it's okay like that too
        done
done

# now do whatever you want with the information
if [ "$CRON_IS_PARENT" == "1" ]; then
        CRON_CALL="Y"
else
        CRON_CALL="N"
fi

echo "CRON Call: ${CRON_CALL}"

1
सोलारिस क्रोन पर एक शेल शुरू होता है और शेल स्क्रिप्ट चलाता है, जो खुद एक और शेल शुरू करता है। तो स्क्रिप्ट में पैरेंट पिड क्रोन का पिड नहीं है।
छत

4

यदि आपकी स्क्रिप्ट फ़ाइल द्वारा मंगाई गई है cronऔर इसमें पहली पंक्ति है, #!/bin/bashतो आपको अपने उद्देश्य के लिए माता-पिता का नाम खोजने की आवश्यकता है।

1) cronआपके दिए गए समय पर लागू किया जाता है crontab, शेल 2 निष्पादित करते हुए) शेल आपकी स्क्रिप्ट को निष्पादित करता है 3) आपकी स्क्रिप्ट चल रही है

पैरेंट PID वैरिएबल के रूप में उपलब्ध है $PPIDpsमूल PID की मूल PID पाने की आज्ञा है:

PPPID=`ps h -o ppid= $PPID`

लेकिन हमें कमांड के नाम की आवश्यकता है, न कि पिड की, इसलिए हम कहते हैं

P_COMMAND=`ps h -o %c $PPPID`

अब हमें सिर्फ "क्रोन" के लिए परिणाम का परीक्षण करने की आवश्यकता है

if [ "$P_COMMAND" == "cron" ]; then
  RUNNING_FROM_CRON=1
fi

अब आप अपनी स्क्रिप्ट में कहीं भी परीक्षण कर सकते हैं

if [ "$RUNNING_FROM_CRON" == "1" ]; then
  ## do something when running from cron
else
  ## do something when running from shell
fi

सौभाग्य!


यह केवल लिनक्स पीएस के लिए काम करता है। MacOS (साथ ही लिनक्स, शायद * BSD भी) के लिए, आप निम्नलिखित P_COMMAND का उपयोग कर सकते हैं:P_COMMAND=$(basename -a $(ps h -o comm $PPPID))
16

1

फ्रीबीएसडी या लिनक्स पर काम करता है:

if [ "Z$(ps o comm="" -p $(ps o ppid="" -p $$))" == "Zcron" -o \
     "Z$(ps o comm="" -p $(ps o ppid="" -p $(ps o ppid="" -p $$)))" == "Zcron" ]
then
    echo "Called from cron"
else
    echo "Not called from cron"
fi

आप अपनी इच्छानुसार प्रोसेस ट्री तक जा सकते हैं।


1

प्रश्न का एक सामान्य समाधान "मेरा आउटपुट एक टर्मिनल है या मैं एक स्क्रिप्ट से चल रहा हूं" है:

( : > /dev/tty) && dev_tty_good=y || dev_tty_good=n

0

echo $TERM | mail me@domain.comक्रोन में एक साधारण ने मुझे दिखाया कि लिनक्स और AIX दोनों पर, क्रोन $TERM'गूंगा' पर सेट होता है ।

अब सैद्धांतिक रूप से अभी भी चारों ओर वास्तविक गूंगा टर्मिनल हो सकता है, लेकिन मुझे संदेह है कि ज्यादातर अवसरों के लिए, यह पर्याप्त होना चाहिए ...


0

कोई आधिकारिक जवाब नहीं है, लेकिन यहाँ शीघ्र ( $PS1) और टर्मिनल ( $TERM) चर बहुत अच्छे हैं। कुछ सिस्टम सेट TERM=dumbकरते हैं, जबकि अधिकांश इसे खाली छोड़ देते हैं, इसलिए हम बस या तो जांच करेंगे:

if [ "${TERM:-dumb}$PS1" != "dumb" ]; then
  echo "This is not a cron job"
fi

उपरोक्त कोड "डंब" शब्द का विकल्प बनाता है जब कोई मूल्य नहीं होता है $TERM। इसलिए, सशर्त आग नहीं है जब वहाँ $TERMया $TERM"गूंगा" करने के लिए या यदि सेट कर दिया जाता $PS1चर खाली नहीं है।

मैंने इसे डेबियन 9 ( TERM=), CentOS 6.4 & 7.4 ( TERM=dumb), और FreeBSD 7.3 ( TERM=) पर परीक्षण किया है ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.