2008-10-22 19 views
8

मैं शर्त लगा रहा हूं कि किसी ने पहले से ही इसे हल कर लिया है और शायद मैं Google के लिए गलत खोज शब्द का उपयोग कर रहा हूं, मुझे जवाब देने के लिए, लेकिन यहां मेरी स्थिति है।क्रॉन स्क्रिप्ट कतार के रूप में कार्य करने या क्रॉन के लिए एक कतार?

मेरे पास एक स्क्रिप्ट है जिसे मैं चलाने के लिए चाहता हूं, लेकिन मैं इसे केवल तभी चलाने के लिए चाहता हूं जब एक समय में केवल एक ही हो। (एक साथ स्क्रिप्ट को नहीं चला सकता)

अब चिपचिपा हिस्सा यह है कि मेरे पास "myhappyschedule" नामक एक टेबल है जिसमें मुझे आवश्यक डेटा और निर्धारित समय है। इस तालिका में एक ही समय में कई निर्धारित समय हो सकते हैं, प्रत्येक व्यक्ति इस स्क्रिप्ट को चलाएगा। इसलिए अनिवार्य रूप से मुझे प्रत्येक बार स्क्रिप्ट की आग की कतार की आवश्यकता होती है और उन्हें सभी को समाप्त होने से पहले प्रत्येक के लिए प्रतीक्षा करने की आवश्यकता होती है। (कभी-कभी स्क्रिप्ट को कई बार मिनटों में निष्पादित करने में केवल एक मिनट लग सकता है)

मैं जो कुछ करने के बारे में सोच रहा हूं वह एक स्क्रिप्ट बना रहा है जो हर 5 मिनट में myhappyschedule की जांच करता है और निर्धारित किए गए लोगों को इकट्ठा करता है, उन्हें रखता है एक कतार में जहां एक और स्क्रिप्ट क्रम में प्रत्येक 'नौकरी' या कतार में प्रक्षेपण निष्पादित कर सकती है। यह सब गन्दा लगता है।

इसे और अधिक बनाने के लिए - मुझे यह कहना चाहिए कि मैं उपयोगकर्ताओं को myhappyschedule में चीजों को शेड्यूल करने और क्रोंटैब संपादित करने की अनुमति नहीं दे रहा हूं।

इस बारे में क्या किया जा सकता है? फ़ाइल लॉक और स्क्रिप्ट कॉल स्क्रिप्ट्स?

उत्तर

3

एक स्तंभ exec_status को (शायद भी time_started और time_finished, स्यूडोकोड देखें)

निम्नलिखित क्रॉन स्क्रिप्ट हर x मिनट

क्रॉन स्क्रिप्ट के स्यूडोकोड चलाने जोड़ने , स्क्रिप्ट पहले जांचती है कि कोई भी आदेश नहीं चल रहा है, तो पहले चरण में अभी तक रन कमांड चलाता है, जब तक कि दिए गए पल में चलाने के लिए कोई और आदेश नहीं है। साथ ही, आप देख सकते हैं कि डेटाबेस से पूछताछ करके कौन सा आदेश निष्पादित हो रहा है।

एक संभावित pitfall: यदि क्रॉन स्क्रिप्ट की हत्या हो जाती है, तो एक निर्धारित कार्य "execing_now" स्थिति में रहेगा। प्रारंभ और अंत में पिड लॉक यही है: यह देखने के लिए कि क्रॉन स्क्रिप्ट ठीक से समाप्त हो गई है या नहीं। पडलॉक बनाने/चेक करने के छद्म कोड:

if exists pidlockfile then 
    check if process id given in file exists 
    if not exists then 
    update myhappytable set exec_status = error_cronscript_died_while_executing_this 
     where exec_status == executing_now 
    delete pidlockfile 
    else (previous instance still running) 
    exit 
    endif 
endif 
create pidlockfile containing cron script process id 
+0

यह छद्म कोड है जो मुझे नौकरी कतार के संबंध में एक बुरी तरह असमर्थनीय पथ का नेतृत्व करता है। बहुत बहुत धन्यवाद Piskvor। – bouvard

2

आप अपनी अगली रन शेड्यूल करने के लिए अपनी स्क्रिप्ट के अंदर (1) कमांड का उपयोग कर सकते हैं। इससे पहले कि यह निकल जाए, यह अगले रन टाइम के लिए myhappyschedule की जांच कर सकता है। आपको वास्तव में क्रॉन की ज़रूरत नहीं है।

[create/check pid lock (optional, but see "A potential pitfall" below)] 
get number of rows from myhappytable where (exec_status == executing_now) 
if it is > 0, exit 
begin loop 
    get one row from myhappytable 
    where (exec_status == not_yet_run) and (scheduled_time <= now) 
    order by scheduled_time asc 
    if no such row, exit 
    set row exec_status to executing_now (maybe set time_started to now) 
    execute whatever command the row contains 
    set row exec_status to completed 
    (maybe also store the command output/return as well, set time_finished to now) 
end loop 
[delete pid lock file (complementary to the starting pid lock check)] 

इस तरह:

+0

खैर .. कि कुछ मैं के बारे में सोचना नहीं किया। मुझे आश्चर्य है कि स्क्रिप्ट चल रहा है, जबकि एक निर्धारित समय बीत सकता है। मान लें कि यह 8:00 बजे निष्पादित होता है और स्क्रिप्ट 10 मिनट के लिए चलती है और किसी भी समय याद आती है जो इसे शुरू करने के अंत और अंत समय के बीच निर्धारित होती है। – user30413

+0

अच्छा बिंदु। आप myhappyschedule को संपादित करने वाली किसी भी प्रक्रिया में एटीक में हेरफेर करना चाह सकते हैं। मुझे इसके बारे में दोपहर के भोजन के बारे में सोचना होगा। –

+0

मुझे लगता है कि यदि आपकी स्क्रिप्ट अपने रन के अंत में myhappyschedule की जांच करती है, और अपने अगले समय रन आउट करने के लिए myhappyschedule के प्रारंभिक निर्धारित समय को पॉप करता है, तो यह इरादे के रूप में काम करेगा। कुंजी अभी भी myhappyschedule में सबसे शुरुआती समय लेना है। –

0

क्यूइंग समस्या के समाधान के लिए शोध करते समय मैं इस प्रश्न में आया। यहां खोज रहे किसी और के लाभ के लिए मेरा समाधान है।

इसे एक क्रॉन के साथ संयोजित करें जो नियत होने के बाद नौकरियां शुरू करता है (भले ही वे एक ही समय में चलने के लिए निर्धारित हैं) और यह आपके द्वारा वर्णित समस्या को हल करता है।

समस्या


  • स्क्रिप्ट के सबसे एक उदाहरण पर चलना चाहिए।
  • हम जितनी जल्दी हो सके उन्हें संसाधित करने के अनुरोधों को क्यू करना चाहते हैं।

यानी। हमें स्क्रिप्ट के लिए एक पाइपलाइन की जरूरत है।

समाधान:


किसी भी स्क्रिप्ट को एक पाइप लाइन बनाएँ। एक छोटी बैश स्क्रिप्ट (आगे नीचे) का उपयोग कर किया गया।

स्क्रिप्ट के रूप में
./pipeline "<any command and arguments go here>"

उदाहरण कहा जा सकता है:

./pipeline sleep 10 & 
./pipeline shabugabu & 
./pipeline single_instance_script some arguments & 
./pipeline single_instance_script some other_argumnts & 
./pipeline "single_instance_script some yet_other_arguments > output.txt" & 
..etc 

स्क्रिप्ट प्रत्येक आदेश के लिए एक नया named pipe पैदा करता है। तो ऊपर नाम बनाएंगे पाइप: sleep, shabugabu, और single_instance_script

इस मामले में प्रारंभिक कॉल एक पाठक शुरू करने और some arguments तर्कों के रूप के साथ single_instance_script चलेंगे। एक बार कॉल पूरा करता है, पाठक पाइप बंद अगले अनुरोध हड़पने जाएगा और some other_arguments साथ निष्पादित, पूर्ण, अगले आदि हड़पने ...

यह स्क्रिप्ट इतनी प्रक्रियाओं का अनुरोध पर एक पृष्ठभूमि काम के रूप में यह फोन (& को अवरुद्ध कर देगा अंत) या at (at now <<< "./pipeline some_script" के साथ एक अलग प्रक्रिया के रूप में)

#!/bin/bash -Eue 

# Using command name as the pipeline name 
pipeline=$(basename $(expr "$1" : '\(^[^[:space:]]*\)')).pipe 
is_reader=false 

function _pipeline_cleanup { 
     if $is_reader; then 
       rm -f $pipeline 
     fi 
     rm -f $pipeline.lock 

     exit 
} 
trap _pipeline_cleanup INT TERM EXIT 

# Dispatch/initialization section, critical 
lockfile $pipeline.lock 
     if [[ -p $pipeline ]] 
     then 
       echo "$*" > $pipeline 
       exit 
     fi 

     is_reader=true 
     mkfifo $pipeline 
     echo "$*" > $pipeline & 
rm -f $pipeline.lock 

# Reader section 
while read command < $pipeline 
do 
     echo "$(date) - Executing $command" 
     ($command) &> /dev/null 
done 
संबंधित मुद्दे