2009-06-23 10 views
77

मैंने कुछ समाधान देखा है, जिसमें घड़ी और बस पृष्ठभूमि में एक लूपिंग (और सो रही) स्क्रिप्ट चल रही है, लेकिन कुछ भी आदर्श नहीं रहा है।प्रत्येक 15 सेकंड चलाने के लिए यूनिक्स स्क्रिप्ट कैसे प्राप्त करें?

मैं एक स्क्रिप्ट प्रत्येक 15 सेकंड चलाने की जरूरत है, और के बाद से क्रॉन सेकंड का समर्थन नहीं करेंगे, मैं कुछ और पता लगाना करने के लिए छोड़ रहा हूँ।

यूनिक्स पर हर 15 सेकंड में एक स्क्रिप्ट चलाने के लिए सबसे मजबूत और कुशल तरीका क्या है? रीबूट के बाद स्क्रिप्ट को भी चलाने की आवश्यकता है।

+1

पर एक नज़र कब तक इसे चलाने के लिए ले करता है ले लो? –

उत्तर

73

मैं एक स्क्रिप्ट हर मिनट चलाने के लिए क्रॉन उपयोग करें, और है कि स्क्रिप्ट रन के बीच एक 15 सेकंड नींद के साथ अपनी स्क्रिप्ट में चार बार चलाने होगा।

(यह मान लिया गया है अपनी स्क्रिप्ट चलाने के लिए जल्दी है - आप नींद में अपना समय नहीं तो समायोजित कर सकते हैं।)

इस तरह, आप cron के सभी लाभों के साथ ही अपने 15 सेकंड रन अवधि मिलता है।

संपादित करें: नीचे @ बीएमबी की टिप्पणी भी देखें।

+0

* मुट्ठी हिलाता है * हे –

+0

@ एडेन: हा! मेरी दासता, हम फिर से मिलते हैं! – RichieHindle

+50

यदि स्क्रिप्ट लगातार चलने में कितनी देर तक चलती है, तो स्क्रिप्ट की चार प्रतियां बनाएं। एक शुरू करने से पहले 15 सेकंड सोता है, एक और 30, एक और 45, और एक और शून्य। फिर हर चार मिनट में चलाएं। – bmb

13

पृष्ठभूमि में इस चल नहीं होगा यह करते हैं?

#!/bin/sh 
while [ 1 ]; do 
    echo "Hell yeah!" & 
    sleep 15 
done 

यह जितना सक्षम हो उतना कुशल है। महत्वपूर्ण हिस्सा केवल हर 15 सेकंड में निष्पादित हो जाता है और स्क्रिप्ट शेष समय सोती है (इस प्रकार चक्र बर्बाद नहीं करती है)।

+7

संपादन कम से कम 8 अक्षर होना चाहिए (जो बेवकूफ है, IMHO) इसलिए मैं लाइन 3 के अंत में '&' जोड़ नहीं सका। किसी भी मामले में, जैसा कि है, यह हर 15 सेकंड में नहीं चलता है। यह हर "15 सेकंड + हालांकि लंबे समय तक 'echo हैलो' चलाने के लिए चलाता है"। जो 0.01 सेकंड हो सकता है; 1 9 घंटे हो सकता है। –

257

आप क्रॉन से स्क्रिप्ट चलाने के जोर देते हैं:

* * * * * /foo/bar/your_script 
* * * * * sleep 15; /foo/bar/your_script 
* * * * * sleep 30; /foo/bar/your_script 
* * * * * sleep 45; /foo/bar/your_script 

और/foo/बार/your_script

+16

यह बहुत चालाक है। +1 – SingleNegationElimination

+4

यह मेरे लिए पूरी तरह से काम किया। पृष्ठभूमि कार्य का उपयोग करने के ऊपर इस पर हलोजन कई बाल प्रक्रियाओं को जन्म दे रहा था और मेरे अंत में स्मृति समस्याएं पैदा कर रहा था। – Hacknightly

+2

यदि php स्क्रिप्ट चलाना यह करता है: '* * * * * नींद 15; php/foo/bar/your_script' – ImaginedDesign

0

उपयोग nanosleep(2) को & पथ अपनी स्क्रिप्ट नाम बदलें। यह संरचना timespec का उपयोग करता है जिसका प्रयोग नैनोसेकंद परिशुद्धता के साथ समय के अंतराल को निर्दिष्ट करने के लिए किया जाता है।

struct timespec { 
      time_t tv_sec;  /* seconds */ 
      long tv_nsec;  /* nanoseconds */ 
     }; 
+1

मैं आगे बढ़ने जा रहा हूं और अनुमान लगाता हूं कि उन्हें नैनोसेकंद परिशुद्धता की आवश्यकता नहीं है, क्योंकि वे हर 15 सेकंड में जो चीज फैल रहे हैं वह शेल स्क्रिप्ट है, कर्नेल थ्रेड नहीं। –

+0

@ पार्थियनशॉट शायद लेकिन आप कभी नहीं जानते। –

-2

निष्पादन के संभावित अतिव्यापी बचने के लिए, कि thread में वर्णित के रूप में एक ताला तंत्र का उपयोग करें।

+2

-1 ओपी ने यह नहीं कहा कि उसे निष्पादन ओवरलैपिंग से बचने के लिए जरूरी है; चीज पुनर्वित्त हो सकती है। इसके अलावा, यह सवाल का जवाब नहीं देता है। –

+0

यह एक अच्छी टिप्पणी होगी, मैं –

14

ऊपर का संशोधित संस्करण:

mkdir /etc/cron.15sec 
mkdir /etc/cron.minute 
mkdir /etc/cron.5minute 

को/etc/crontab जोड़ें:

* * * * * root run-parts /etc/cron.15sec > /dev/null 2> /dev/null 
* * * * * root sleep 15; run-parts /etc/cron.15sec > /dev/null 2> /dev/null 
* * * * * root sleep 30; run-parts /etc/cron.15sec > /dev/null 2> /dev/null 
* * * * * root sleep 45; run-parts /etc/cron.15sec > /dev/null 2> /dev/null 

* * * * * root run-parts /etc/cron.minute > /dev/null 2> /dev/null 
*/5 * * * * root run-parts /etc/cron.5minute > /dev/null 2> /dev/null 
0
#! /bin/sh 

# Run all programs in a directory in parallel 
# Usage: run-parallel directory delay 
# Copyright 2013 by Marc Perkel 
# docs at http://wiki.junkemailfilter.com/index.php/How_to_run_a_Linux_script_every_few_seconds_under_cron" 
# Free to use with attribution 

if [ $# -eq 0 ] 
then 
    echo 
    echo "run-parallel by Marc Perkel" 
    echo 
    echo "This program is used to run all programs in a directory in parallel" 
    echo "or to rerun them every X seconds for one minute." 
    echo "Think of this program as cron with seconds resolution." 
    echo 
    echo "Usage: run-parallel [directory] [delay]" 
    echo 
    echo "Examples:" 
    echo " run-parallel /etc/cron.20sec 20" 
    echo " run-parallel 20" 
    echo " # Runs all executable files in /etc/cron.20sec every 20 seconds or 3 times a minute." 
    echo 
    echo "If delay parameter is missing it runs everything once and exits." 
    echo "If only delay is passed then the directory /etc/cron.[delay]sec is assumed." 
    echo 
    echo 'if "cronsec" is passed then it runs all of these delays 2 3 4 5 6 10 12 15 20 30' 
    echo "resulting in 30 20 15 12 10 6 5 4 3 2 executions per minute." 
    echo 
    exit 
fi 

# If "cronsec" is passed as a parameter then run all the delays in parallel 

if [ $1 = cronsec ] 
then 
    $0 2 & 
    $0 3 & 
    $0 4 & 
    $0 5 & 
    $0 6 & 
    $0 10 & 
    $0 12 & 
    $0 15 & 
    $0 20 & 
    $0 30 & 
    exit 
fi 

# Set the directory to first prameter and delay to second parameter 

dir=$1 
delay=$2 

# If only parameter is 2,3,4,5,6,10,12,15,20,30 then automatically calculate 
# the standard directory name /etc/cron.[delay]sec 

if [[ "$1" =~ ^(2|3|4|5|6|10|12|15|20|30)$ ]] 
then 
    dir="/etc/cron.$1sec" 
    delay=$1 
fi 

# Exit if directory doesn't exist or has no files 

if [ ! "$(ls -A $dir/)" ] 
then 
    exit 
fi 

# Sleep if both $delay and $counter are set 

if [ ! -z $delay ] && [ ! -z $counter ] 
then 
    sleep $delay 
fi 

# Set counter to 0 if not set 

if [ -z $counter ] 
then 
    counter=0 
fi 

# Run all the programs in the directory in parallel 
# Use of timeout ensures that the processes are killed if they run too long 

for program in $dir/* ; do 
    if [ -x $program ] 
    then 
     if [ "0$delay" -gt 1 ] 
     then 
     timeout $delay $program &> /dev/null & 
     else 
     $program &> /dev/null & 
     fi 
    fi 
done 

# If delay not set then we're done 

if [ -z $delay ] 
then 
    exit 
fi 

# Add delay to counter 

counter=$(($counter + $delay)) 

# If minute is not up - call self recursively 

if [ $counter -lt 60 ] 
then 
    . $0 $dir $delay & 
fi 

# Otherwise we're done 
0

मेरे पिछले जवाब के बाद से मैं एक और समाधान है कि विभिन्न और शायद बेहतर है के साथ आया था । यह कोड माइक्रोसॉन्ड परिशुद्धता के साथ 60 मिनट से अधिक मिनटों को चलाने की अनुमति देता है। आप इस काम करने के लिए usleep कार्यक्रम की जरूरत है। एक सेकंड में 50 गुना तक अच्छा होना चाहिए।

#! /bin/sh 

# Microsecond Cron 
# Usage: cron-ms start 
# Copyright 2014 by Marc Perkel 
# docs at http://wiki.junkemailfilter.com/index.php/How_to_run_a_Linux_script_every_few_seconds_under_cron" 
# Free to use with attribution 

basedir=/etc/cron-ms 

if [ $# -eq 0 ] 
then 
    echo 
    echo "cron-ms by Marc Perkel" 
    echo 
    echo "This program is used to run all programs in a directory in parallel every X times per minute." 
    echo "Think of this program as cron with microseconds resolution." 
    echo 
    echo "Usage: cron-ms start" 
    echo 
    echo "The scheduling is done by creating directories with the number of" 
    echo "executions per minute as part of the directory name." 
    echo 
    echo "Examples:" 
    echo " /etc/cron-ms/7  # Executes everything in that directory 7 times a minute" 
    echo " /etc/cron-ms/30  # Executes everything in that directory 30 times a minute" 
    echo " /etc/cron-ms/600 # Executes everything in that directory 10 times a second" 
    echo " /etc/cron-ms/2400 # Executes everything in that directory 40 times a second" 
    echo 
    exit 
fi 

# If "start" is passed as a parameter then run all the loops in parallel 
# The number of the directory is the number of executions per minute 
# Since cron isn't accurate we need to start at top of next minute 

if [ $1 = start ] 
then 
    for dir in $basedir/* ; do 
     $0 ${dir##*/} 60000000 & 
    done 
    exit 
fi 

# Loops per minute and the next interval are passed on the command line with each loop 

loops=$1 
next_interval=$2 

# Sleeps until a specific part of a minute with microsecond resolution. 60000000 is full minute 

usleep $(($next_interval - 10#$(date +%S%N)/1000)) 

# Run all the programs in the directory in parallel 

for program in $basedir/$loops/* ; do 
    if [ -x $program ] 
    then 
     $program &> /dev/null & 
    fi 
done 

# Calculate next_interval 

next_interval=$(($next_interval % 60000000 + (60000000/$loops))) 

# If minute is not up - call self recursively 

if [ $next_interval -lt $((60000000/$loops * $loops)) ] 
then 
    . $0 $loops $next_interval & 
fi 

# Otherwise we're done 
+1

ऊपर उठाने के बजाय मूल को संपादित करूँगा! –

1

मैंने क्रॉन से तेज शेड्यूलर लिखा था। मैंने एक ओवरलैपिंग गार्ड भी लागू किया है। यदि पिछला अभी भी चल रहा है तो आप नई प्रक्रिया शुरू करने के लिए शेड्यूलर को कॉन्फ़िगर कर सकते हैं। https://github.com/sioux1977/scheduler/wiki

संबंधित मुद्दे