हर महीने के आखिरी दिन का शेड्यूल करें


10

मैं महीने के आखिरी दिन एक स्क्रिप्ट शेड्यूल करने के निर्देश से पढ़ता हूं:

नोट:
अचरज पाठक सोच रहा होगा कि आप हर महीने के आखिरी दिन को कैसे निष्पादित करने के लिए एक कमांड सेट कर पाएंगे क्योंकि आप हर महीने कवर करने के लिए दिन के समय का मूल्य निर्धारित नहीं कर सकते हैं। इस समस्या ने लिनक्स और यूनिक्स प्रोग्रामर्स को त्रस्त कर दिया है, और कई अलग-अलग समाधानों को जन्म दिया है। एक सामान्य तरीका यह है कि यदि कल की तारीख 01 है, तो यह जाँचने के लिए दिनांक कमांड का उपयोग किया जाता है

00 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command1

यह हर दिन दोपहर 12 बजे चेक करता है कि क्या यह महीने का आखिरी दिन है, और यदि ऐसा है, तो क्रॉन कमांड चलाता है।

यहाँ छवि विवरण दर्ज करें

कैसे [`date +%d -d tomorrow` = 01 ]काम करता है ?
क्या यह सही है then; command1?


क्या आप सुनिश्चित हैं कि यह शब्दशः क्या है? जैसा कि यहां लिखा गया है कि यह वास्तव में काम नहीं करता है।
माइकल होमर

मैंने स्नैपशॉट पोस्ट किया। @ माइकलहोमर
पथरी

धन्यवाद! मैंने इसे बनाने के लिए प्रारूपण के साथ कहा है - यह अभी भी काफी सही नहीं है, लेकिन यह वही है जो तस्वीर कहती है।
माइकल होमर

1
याद आ रही है ; endif?
danblack

यह काम नहीं करता है। इसमें सिंटैक्स त्रुटियां हैं: अंत में कोई स्थान नहीं [और बाद में नहीं fi। इसके अलावा, %crontabs में विशेष है।
Kusalananda

जवाबों:


17

सार

सही कोड होना चाहिए:

#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"

इस स्क्रिप्ट end_of_month.shको कॉल करें और क्रोन में कॉल बस है:

00 12 28-31 * * /path/to/script/end_of_month.sh command

वह स्क्रिप्ट चलाएगा end_of_month(जो आंतरिक रूप से जांच करेगा कि दिन महीने का अंतिम दिन है) केवल 28, 29, 30 और 31 के दिन। किसी भी अन्य दिन महीने के अंत की जांच करने की कोई आवश्यकता नहीं है।

पुरानी पोस्ट।

वह रिचर्ड ब्लम, क्रिस्टीन ब्रेस्नाप पीपी 442, तृतीय संस्करण, जॉन विले एंड संस © 2015 की पुस्तक "लिनक्स कमांड लाइन और शेल स्क्रिप्टिंग बाइबिल" से एक उद्धरण है।

हां, यह वही है जो यह कहता है, लेकिन यह गलत / अधूरा है:

  • एक समापन याद आ रहा है fi
  • [निम्न और निम्न के बीच स्थान की आवश्यकता है `
  • इसके बजाय $ (…) का उपयोग करने की दृढ़ता से अनुशंसा की जाती है `…`
  • यह महत्वपूर्ण है कि आप विस्तार जैसे उद्धरणों का उपयोग करें"$(…)"
  • के ;बाद एक अतिरिक्त हैthen

मुझे कैसे पता चलेगा? (ठीक है, अनुभव ☺ द्वारा) लेकिन आप शेलचेक की कोशिश कर सकते हैं । पुस्तक से कोड (तारांकन के बाद) पेस्ट करें और यह आपको ऊपर सूचीबद्ध त्रुटियों को दिखाएगा जो एक "लापता शेबंग" है। शेलचेक में किसी भी त्रुटि के बिना एक स्क्रिप्ट यह है:

#!/bin/sh if [ "$(date +%d -d tomorrow)" = 01 ] ; then script.sh; fi

वह साइट काम करती है क्योंकि जो लिखा गया था वह "शेल कोड" है। यह एक सिंटैक्स है जो कई गोले में काम करता है।

शेलचेक का उल्लेख नहीं करने वाले कुछ मुद्दे हैं:

  • यह मानकर चल रहा है कि दिनांक आदेश GNU दिनांक संस्करण है। -dउस विकल्प के साथ जो मान के tomorrowरूप में स्वीकार करता है (बिजीबॉक्स के पास -d विकल्प होता है, लेकिन कल नहीं समझ में आता है और BSD के पास एक -dविकल्प है लेकिन समय के "प्रदर्शन" से संबंधित नहीं है)।

  • सभी विकल्पों के बाद प्रारूप को सेट करना बेहतर है date -d tomorrow +'%d'

  • क्रोन प्रारंभ समय हमेशा स्थानीय समय में होता है, जो कि एक दिन की गणना की तुलना में 1 घंटे पहले एक नौकरी शुरू कर सकता है यदि डीएसटी (दिन के समय की बचत का समय) सेट हो गया या परेशान हो गया।

हमने जो किया वह एक शेल स्क्रिप्ट है जिसे क्रोन के साथ कहा जा सकता है। हम इस तरह (अंत में, सही कोड) निष्पादित करने के लिए प्रोग्राम या कमांड के तर्कों को स्वीकार करने के लिए स्क्रिप्ट को संशोधित कर सकते हैं:

#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"

इस स्क्रिप्ट end_of_month.shको कॉल करें और क्रोन में कॉल बस है:

00 12 28-31 * * /path/to/script/end_of_month.sh command

वह स्क्रिप्ट चलाएगा end_of_month(जो आंतरिक रूप से जांच करेगा कि दिन महीने का अंतिम दिन है) केवल 28, 29, 30 और 31 के दिन। किसी भी अन्य दिन महीने के अंत की जांच करने की कोई आवश्यकता नहीं है।

सुनिश्चित करें कि सही मार्ग शामिल है। CAT के अंदर PATH उपयोगकर्ता PATH के समान नहीं होगा (संभावना नहीं है)।

ध्यान दें कि महीने की स्क्रिप्ट के एक छोर का परीक्षण किया गया है (जैसा कि नीचे बताया गया है) जो कई अन्य उपयोगिताओं या स्क्रिप्ट को कॉल कर सकता है।

यह अतिरिक्त समस्या से भी बचाएगा, जो क्रोन पूरी कमांड लाइन के साथ उत्पन्न होती है:

  • क्रोन कमांड लाइन को किसी पर भी विभाजित करता है, %भले ही या तो ( 'या "केवल \यहां काम करता है) के साथ उद्धृत किया गया हो । यह एक सामान्य तरीका है जिसमें क्रोन नौकरियां विफल होती हैं।

यदि end_of_month.shस्क्रिप्ट कुछ तारीखों पर सही ढंग से काम करती है (बिना काम किए इसे पूरा करने के लिए महीने के अंत तक प्रतीक्षा करें तो आप इसे देख सकते हैं)

$ faketime 2018/10/31 ./end_of_month echo "Command will be executed...."
Command will be executed....

ast-open date(या dateksh93 का बिल्ट यदि ksh93 को ast-open के भाग के रूप में बनाया गया था) समर्थन करता है date -d tomorrow +%sया date +%s tomorrow)।
स्टीफन चेज़लस

2
अनुभव ने (कई बार) साबित किया है कि स्क्रिप्ट को सही तरीके से परीक्षण करने के लिए यह बहुत बेहतर है कि यह निर्धारित समय से खत्म होने तक इंतजार करे कि यह निर्धारित नौकरी नहीं मिली। उस * * * * * echo "$(date -u +'date %c')" >>~/testfileअभ्यस्त काम की खोज की तरह, क्योंकि कोई भी उद्धरण देना भूल गया \%(जो कि डिबग करना मुश्किल हो जाता है अगर हर महीने केवल एक बार कोशिश की जाए तो यह संभव है)। @ कुसलानंद
इसहाक

8

यह मानते हुए कि सिंटैक्स त्रुटियां ठीक हो गई हैं, और कम वर्बोज़ होने के लिए कमांड को थोड़ा सुधार दिया गया है:

00 12 28-31 * * [ "$( date -d tomorrow +\%d )" != "01" ] || command1

यह चलता है date +%d -d tomorrow(यह मानते हुए कि यह GNU dateहै जिसका उपयोग किया जाता है) कल की तारीख को दो अंकों की संख्या के रूप में प्राप्त करता है। यदि संख्या नहीं है 01, तो आज महीने का अंतिम दिन नहीं है। उस स्थिति में, परीक्षण सफल होता है और निष्पादित नहीं होता command1है । यह काम दोपहर के समय चलाया जाता है जो संभवतः महीने का आखिरी दिन हो सकता है।

मूल आदेश:

00 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command1

इसके कुछ मुद्दे हैं:

  • के बाद कोई जगह नहीं [
  • एक के ;बाद एक सीधे then
  • %क्रोन जॉब विनिर्देशों में विशेष है और इसे \%(देखें man 5 crontab) के रूप में भाग जाना चाहिए ।
  • fiअंत के साथ मेल खाता कोई अंतिम नहीं है if

2
इसके [ ... ] && command1बजाय का उपयोग करने के साथ समस्या यह if...है कि उन दिनों पर जो महीने का अंतिम दिन नहीं है, क्रोन नौकरी एक गैर-शून्य निकास स्थिति के साथ समाप्त हो जाएगी और उस विफलता को रिपोर्ट करना पड़ सकता है। [ "$(...)" != 01 ] || command1समस्या से बचने का एक और तरीका है।
स्टीफन चेज़लस

1
मूल कोड के साथ एक और समस्या ;बीच thenऔर है command1
स्टीफन चेज़लस

@ स्टीफनचेज़ेलस एक और कारण है कि मैं वन-लाइनर्स को नापसंद करता हूं, उन्हें पढ़ना मुश्किल है।
Kusalananda

कमांड के लगातार रन के बीच समय का अंतर एक पूर्णांक राशि (24 घंटे) दिनों का नहीं हो सकता है क्योंकि डीएसटी परिवर्तन क्रोन के प्रारंभ समय को स्थानांतरित कर देगा।
इसहाक

3
@cat इससे कोई फर्क नहीं पड़ता कि आप कैसे उद्धरण देते हैं, "या '(छोड़कर \), प्रतिशत संकेत %क्रोन को दो भागों में लाइन को तोड़ देगा। असफल होने के लिए क्रोन पाने का एक सामान्य तरीका है।
इसहाक

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