हमेशा के लिए हर x सेकंड में एक यूनिक्स कमांड दोहराएं


480

एक अंतर्निहित यूनिक्स कमांड है repeatजिसका पहला तर्क एक कमांड को दोहराने के लिए कई बार है, जहां कमांड (किसी भी तर्क के साथ) शेष तर्कों द्वारा निर्दिष्ट किया जाता है repeat

उदाहरण के लिए,

% repeat 100 echo "I will not automate this punishment."

दिए गए तार को 100 बार गूँजेंगे और फिर रुकेंगे।

मुझे एक समान कमांड चाहिए - चलो इसे कॉल करें forever- जो समान रूप से काम करता है सिवाय पहले तर्क के दोहराए जाने के बीच रुकने के लिए सेकंड की संख्या है, और यह हमेशा के लिए दोहराता है। उदाहरण के लिए,

% forever 5 echo "This will get echoed every 5 seconds forever and ever."

मैंने सोचा कि अगर मैं इसे लिखने से पहले ऐसा कुछ मौजूद है, तो मैं पूछूंगा। मुझे पता है कि यह 2-लाइन पर्ल या पायथन स्क्रिप्ट की तरह है, लेकिन शायद ऐसा करने के लिए एक अधिक मानक तरीका है। यदि नहीं, तो अपनी पसंदीदा स्क्रिप्टिंग भाषा, रोसेटा स्टोन शैली में समाधान पोस्ट करने के लिए स्वतंत्र महसूस करें ।

पुनश्च: हो सकता है कि ऐसा करने का एक बेहतर तरीका repeatदोनों को दोहराने के लिए कई बार की संख्या को सामान्य करना होगा (-1 अर्थ अनन्तता के साथ) और दोहराए जाने के बीच सोने के लिए सेकंड की संख्या। उपरोक्त उदाहरण तब बनेंगे:

% repeat 100 0 echo "I will not automate this punishment."
% repeat -1 5 echo "This will get echoed every 5 seconds forever."

1
क्यों नहीं: बार-बार [-t समय] [-n नंबर] कमांड [args ...]?
जोनाथन लेफ्लर

17
ठंडा। दुर्भाग्य से दोनों मेरे Ubuntu पर और मेरे AIX दोहराने है आदेश नहीं मिला । क्या आप ऐसा कर सकते हैं type repeatऔर मुझे बता सकते हैं कि कहां से आ रहा है?

3
मैं उबंटू में भी हूं और रिपीट इंस्टाल नहीं है। इसे कैसे स्थापित किया जाए, इस बारे में कोई जानकारी उपयोगी होगी।
रोरी डेसी

7
repeatcsh और tsh में एक अंतर्निहित कमांड है।
कीथ थॉम्पसन

2
@KeithThompson, csh, tcsh और zsh । यद्यपि यह एक
बिलियन

जवाबों:


615

watchआदेश का प्रयास करें ।

Usage: watch [-dhntv] [--differences[=cumulative]] [--help] [--interval=<n>] 
             [--no-title] [--version] <command>`

इसलिए कि:

watch -n1  command

कमांड को हर सेकेंड (अच्छी तरह से, तकनीकी रूप से, हर एक सेकंड के लिए और इसके कम-से-कम और कार्यान्वयन के रूप में) commandचलने में लगने वाले समय को दो सेकंड के बीच में एक सेकंड की नींद के लिए, हमेशा के लिए चलाएंगे ।watchprocpsbusyboxcommand

क्या आप execइसके बजाय कमांड का sh -cउपयोग करना चाहते हैं , -xविकल्प का उपयोग करें :

watch -n1 -x command

MacOS पर, आप Mac Portswatch से प्राप्त कर सकते हैं :

port install watch

या आप इसे Homebrew से प्राप्त कर सकते हैं :

brew install watch

2
इसे स्थापित करने के लिए आप MacPorts का उपयोग कर सकते हैं। सूडो पोर्ट इनस्टॉल वॉच

10
यह भी homebrew (काढ़ा स्थापित घड़ी) में उपलब्ध है।
लाइल

28
एक नए शक्तिशाली उपकरण के लिए +1। मैं करता था while true; do X; sleep Y; done- यह बेहतर तरीका है।
एडम मटन

4
इस टूल के साथ समस्या (उबंटू पर कम से कम) यह है कि यह फुलस्क्रीन को मजबूर करता है, इसलिए यदि मैं कुछ आवधिक जानकारी डंप कर रहा हूं, तो मैं पिछली जानकारी खो देता हूं।
बजे स्कॉर्पियोडावॉग

4
इसे cmdwatchFreeBSD (बंदरगाहों से sysutils/cmdwatch) पर बुलाया जाता है ।
Ouki

243

दे घुमा के

while+ sleep:

while true
do 
    echo "Hi"
    sleep 1
done

यहाँ एक शॉर्टहैंड वन-लाइनर के रूप में एक ही बात है (नीचे टिप्पणी से):

while sleep 1; do echo "Hi"; done

का उपयोग करता है ;अलग आदेशों के लिए और का उपयोग करता है sleep 1के लिए whileके बाद से यह हमेशा सच रिटर्न परीक्षण। आप लूप में अधिक कमांड डाल सकते हैं - बस उन्हें अलग करें;


2
मेरा मानना ​​है कि यह एक सामान्य बॉर्न शेल में लिखे गए काम करता है, साथ ही साथ।
dmckee

5
@ का उपयोग करते हुए, ";" विभाजक के रूप में, कमांड को एक लाइन में निष्पादित किया जा सकता है। एक उदाहरण के रूप में
टूनी

56
नींद 1 हमेशा सच होती है, इसलिए आप इसे जब तक चाहें उपयोग कर सकते हैं। दुनिया में सबसे पठनीय बात नहीं है, लेकिन पूरी तरह से कानूनी: सोते समय 1; गूंज "हाय"; किया
डेविड कोस्टा

3
@ दाविद कोस्टा: आपने एक उचित बिंदु बनाया, लेकिन हमेशा सच sleepनहीं होता है। Delay इस तरह के छोरों का उपयोग किया जाता है (हालांकि अब देरी के साथ) क्योंकि नींद की प्रक्रिया को मारने के साथ इसे शान से समाप्त करने का एक तरीका है।
इंनिस मिसी

2
@IncnisMrsi मैंने इसके बारे में नहीं सोचा था, यह वास्तव में शून्य तभी लौटता है जब समय बीत चुका होता है और गैर-शून्य होता है जब यह एक संकेत द्वारा समाप्त हो जाता है। इसे इंगित करने के लिए धन्यवाद
डेविड कोस्टा

71

यह अन्य while+sleepउत्तरों का सिर्फ एक छोटा संस्करण है, यदि आप इस तरह के कार्यों को अक्सर अपनी दिनचर्या के रूप में चला रहे हैं, तो इसका उपयोग करना आपको अनावश्यक कुंजी प्रेस से बचाता है, और यदि आपकी कमांड लाइन को लंबे समय तक समझना शुरू हो जाता है तो यह थोड़ा आसान है। लेकिन यह पहले नींद से शुरू होता है।

यह आम तौर पर तब उपयोगी होता है जब आपको किसी चीज का पालन करने की आवश्यकता होती है, जिसमें मशीन लोड जैसा एक-लाइन आउटपुट होता है:

while sleep 1; do uptime; done

हाँ। इसे UUOC के बगल में प्रलेखित किया जाना चाहिए।
जोहान

10
और अगर आप इसे "वॉच" की तरह संचालित करना चाहते हैं, तो आप कर सकते हैंwhile clear; do date; command;sleep 5; done
जोहान

वाह, while sleepसंयोजन के लिए धन्यवाद , कीस्टोक्स बचाता है!
जॉर्ज वाई।

45

एक समस्या जो अब तक पोस्ट किए गए सभी उत्तरों में है कि कमांड निष्पादित होने का समय तेज हो सकता है। उदाहरण के लिए, यदि आप एक sleep 10कमांड के बीच करते हैं, और कमांड को चलाने में 2 सेकंड लगते हैं, तो यह हर 12 सेकंड में चलने वाला है; यदि इसे चलाने में समय की एक चर राशि लगती है, तो दीर्घकालिक समय पर जब यह अप्रत्याशित हो सकता है।

यह वही हो सकता है जो आप चाहते हैं; यदि ऐसा है, तो अन्य समाधानों में से एक का उपयोग करें, या इस एक का उपयोग करें लेकिन sleepकॉल को सरल बनाएं ।

एक-मिनट के समाधान के लिए, क्रोन नौकरियां निर्दिष्ट समय पर चलेंगी, भले ही प्रत्येक आदेश कितना समय लगे। (वास्तव में एक नई क्रॉन जॉब लॉन्च होगी भले ही पिछला वाला अभी भी चल रहा हो।)

यहां एक सरल पर्ल स्क्रिप्ट है जो अगले अंतराल तक सोता है, इसलिए उदाहरण के लिए 10 सेकंड के अंतराल के साथ कमांड 12:34:00, 12:34:10, 12:34:20, आदि पर चल सकता है, भले ही। कमांड में कई सेकंड लगते हैं। यदि कमांड intervalसेकंड से अधिक चलती है , तो अगले अंतराल को छोड़ दिया जाएगा (क्रोन के विपरीत)। अंतराल युग के सापेक्ष गणना की जाती है, इसलिए 86400 सेकंड (1 दिन) का अंतराल मध्यरात्रि यूटीसी पर चलेगा।

#!/usr/bin/perl

use strict;
use warnings;

if (scalar @ARGV < 2) {
    die "Usage: $0 seconds command [args...]\n";
}

$| = 1;  # Ensure output appears

my($interval, @command) = @ARGV;

# print ">>> interval=$interval command=(@command)\n";

while (1) {
    print "sleep ", $interval - time % $interval, "\n";
    sleep $interval - time % $interval;
    system @command; # TODO: Handle errors (how?)
}


1
बहाव को कम करने के लिए बैश में सरल (हालांकि यह नींद की आज्ञा के कारण बहुत लंबे समय तक उपयोग की जाने वाली खिड़कियों पर बह सकता है और अपने छोटे से निष्पादन समय को जमा कर सकता है): while :; do sleep 1m & command; wait; done
मैथ

1
@ मथ: चतुर। यदि आपके पास वर्तमान शेल में अन्य पृष्ठभूमि प्रक्रियाएं चल रही हैं, तो यह काम नहीं waitकरेगा ( उन सभी की प्रतीक्षा करेगा)। यही कारण है कि बदलकर सुधारी जा सकने वाली है waitकरने के लिए wait $!है, जहां $!की पीआईडी है sleepप्रक्रिया। इसे उत्तर के रूप में पोस्ट करें और मैं इसे बढ़ा दूंगा। लेकिन यह एक इंटरैक्टिव शेल में कुछ बाहरी उत्पादन करता है।
कीथ थॉम्पसन

29

मुझे लगता है कि अब तक के सभी उत्तर या तो बहुत जटिल हैं, या एक अलग प्रश्न का उत्तर देते हैं:

  • "प्रोग्राम को बार-बार कैसे चलाया जाए ताकि प्रोग्राम खत्म होने के बीच एक्स सेकंड्स की देरी हो, और अगला शुरू हो जाए"

असली सवाल यह था:

  • "हर X सेकंड में एक प्रोग्राम कैसे चलाया जाता है"

ये दो बहुत अलग चीजें हैं जब कमांड को पूरा होने में समय लगता है।

उदाहरण के लिए स्क्रिप्ट ले लो foo.sh(दिखाओ यह एक कार्यक्रम है जिसे पूरा होने में कुछ सेकंड लगते हैं)।

#!/bin/bash
# foo.sh
echo `date +"%H:%M:%S"` >> output.txt;
sleep 2.5;
# ---

आप इसे हर सेकंड चलाना चाहते हैं, और अधिकांश सुझाव देंगे watch -n1 ./foo.sh, या while sleep 1; do ./foo.sh; done। हालाँकि, यह आउटपुट देता है:

15:21:20
15:21:23
15:21:27
15:21:30
15:21:34

जो कि हर सेकंड बिल्कुल नहीं चलाया जा रहा है। -pध्वज के साथ भी , जैसा कि man watchपृष्ठ बताता है कि यह हल हो सकता है, परिणाम समान है।

वांछित कार्य को पूरा करने का एक आसान तरीका, जिस पर कुछ स्पर्श होता है, पृष्ठभूमि में कमांड चलाना है। दूसरे शब्दों में:

while sleep 1; do (./foo.sh &) ; done

और यही सब कुछ है।

आप इसे हर 500 ms के साथ चला सकते हैं sleep 0.5, या आपके पास क्या है।


1
जिन लोगों ने अलग-अलग जवाबों पर वोट दिया, वे आपके जवाब की लालित्य को नहीं समझे ...
सर्ज स्ट्रोबंड

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

4
यह सुनिश्चित करने के लिए पृष्ठभूमि के क्रम को उल्टा कर सकते हैं कि एक से अधिक नहीं ।/foo.sh एक समय में चलाया जाता है, लेकिन प्रति सेकंड 1 से अधिक तेज़ नहीं है: while :; do sleep 1 & ./foo.sh; wait; done
गणित

हाँ, यह बहाव होगा, प्रत्येक लूप पर कुछ मिलीसेकंड, लेकिन यह होगा। बनाओ date +"%H:%M:%S.%N"foo.sh में देखना चाहते हैं कि अंश प्रत्येक पाश पर धीरे-धीरे वृद्धि होगी।
इसहाक

हां, यह सही है कि अधिकांश उत्तर शाब्दिक रूप से प्रश्न को संबोधित नहीं करते हैं । लेकिन यह लगभग सुरक्षित शर्त है कि वे जवाब दें कि ओपी क्या चाहता था। यह एक सुरक्षित शर्त होगी यदि ओपी ने वास्तव में एक उत्तर स्वीकार किया है ... लेकिन यह अच्छा है, बशर्ते आप संभावित दुष्प्रभावों से अवगत हों और आप निश्चित हैं कि कमांड का औसत रन समय चक्र समय से अधिक नहीं है।
शुभ जूल

17

इन bash:

bash -c 'while [ 0 ]; do echo "I will not automate this punishment in absurdum."; done'

( echoकिसी भी आदेश द्वारा प्रतिस्थापित किया जा सकता है ...

या में perl:

perl -e 'for (;1;) {print "I will not automate this punishment in absurdum.\n"}'

जहां print "I will not automate this punishment in absurdum.\n"बैकटिक्स (`) से घिरे" किसी भी "कमांड को बदला जा सकता है।

और ठहराव sleepके लिए, लूप के लिए एक स्टेटमेंट जोड़ें :

bash -c 'while [ 0 ]; do echo "I will not automate this punishment in absurdum."; sleep 1; done'

तथा

perl -e 'for (;1;) {print "I will not automate this punishment in absurdum.\n"; sleep 1}'

16
while [ 0 ]यह लिखने का एक बुरा तरीका है। इसका मतलब 0है कि लंबाई के साथ एक स्ट्रिंग है> 0. while [ 1 ]या while [ jeff ]एक ही काम करेगा। लिखने के लिए बेहतर है while true
मिकेल

5
@ मिकेल: याwhile :
कीथ थॉम्पसन

10

हाल ही में किए गए लिनक्स कर्नेल, हाल के लिनक्स कर्नेल, आधारित उत्तर के तहत 4.2।

निष्पादन समय को सीमित करने के लिए, कोई कांटा नहीं है ! केवल अंतर्निहित उपयोग किया जाता है।

इसके लिए, मैं readइसके बजाय अंतर्निहित फ़ंक्शन का उपयोग करता हूं sleep। दुर्भाग्य से यह नोटी सत्र के साथ काम नहीं करेगा ।

अनुरोध के अनुसार त्वरित फ़ंक्शन " repeat":

repeat () {
   local repeat_times=$1 repeat_delay=$2 repeat_foo repeat_sleep
   read -t .0001 repeat_foo
   if [ $? = 1 ] ;then
       repeat_sleep() { sleep $1 ;}
   else
       repeat_sleep() { read -t $1 repeat_foo; }
   fi
   shift 2
   while ((repeat_times)); do
        ((repeat_times=repeat_times>0?repeat_times-1:repeat_times))
        "${@}"
        ((repeat_times))&& ((10#${repeat_delay//.})) &&
            repeat_sleep $repeat_delay
   done
}

उद्धृत स्ट्रिंग्स के साथ थोड़ा परीक्षण:

repeat 3 0 printf "Now: %(%T)T, Hello %s.\n" -1 Guy
Now: 15:13:43, Hello Guy.
Now: 15:13:43, Hello Guy.
Now: 15:13:43, Hello Guy.

repeat -1 .5 printf "Now: %(%T)T, Hello %s.\n" -1 Guy
Now: 15:14:14, Hello Guy.
Now: 15:14:14, Hello Guy.
Now: 15:14:15, Hello Guy.
Now: 15:14:15, Hello Guy.
Now: 15:14:16, Hello Guy.
Now: 15:14:16, Hello Guy.
Now: 15:14:17, Hello Guy.
Now: 15:14:17, Hello Guy.
Now: 15:14:18, Hello Guy.
Now: 15:14:18, Hello Guy.
^C

प्रस्तुत आदेश की बारीकियों और अवधि पर निर्भर करता है ...

हाल ही में लिनक्स कर्नेल के तहत, नैनोसैकेड /proc/timer_listमें समय की जानकारी युक्त एक प्रूफ़ाइल है।

यदि आप दूसरी बार एक कमांड चलाना चाहते हैं, तो आपकी कमांड एक सेकंड से भी कम समय में समाप्त हो जाएगी! और वहाँ से, आपको sleepकेवल शेष वर्तमान सेकंड के लिए है।

यदि देरी अधिक महत्वपूर्ण है और आपके आदेश को महत्वपूर्ण समय की आवश्यकता नहीं है, तो आप कर सकते हैं:

command=(echo 'Hello world.')
delay=10
while :;do
    printf -v now "%(%s)T" -1
    read -t $(( delay-(now%delay) )) foo
    ${command[@]}
  done.

लेकिन अगर आपका लक्ष्य बेहतर बारीकियों को प्राप्त करना है, तो आपको निम्न करना होगा:

एक सेकंड की शुरुआत तक प्रतीक्षा करने के लिए नैनोसेकंड जानकारी का उपयोग करें ...

इसके लिए, मैंने थोड़ा बैश फंक्शन लिखा:

# bash source file for nano wait-until-next-second

mapfile  </proc/timer_list _timer_list
for ((_i=0;_i<${#_timer_list[@]};_i++));do
    ((_c+=${#_timer_list[_i]}))
    [[ ${_timer_list[_i]} =~ ^now ]] && TIMER_LIST_READ=$_c
    [[ ${_timer_list[_i]} =~ offset:.*[1-9] ]] && \
        TIMER_LIST_OFFSET=${_timer_list[_i]//[a-z.: ]} && \
        break
done
unset _i _timer_list _c
readonly TIMER_LIST_OFFSET TIMER_LIST_READ
waitNextSecondHires() {
    local nsnow nsslp
    read -N$TIMER_LIST_READ nsnow </proc/timer_list
    nsnow=${nsnow%% nsecs*}
    nsnow=$((${nsnow##* }+TIMER_LIST_OFFSET))
    nsslp=$((2000000000-10#${nsnow:${#nsnow}-9}))
    read -t .${nsslp:1} foo
}

उन्हें सोर्स करने के बाद, आप कर सकते हैं:

command=(echo 'Hello world.')
while :;do
    waitNextSecondHires
    ${command[@]}
  done.

${command[@]}तुलना करने की तुलना में सीधे कमांड लाइन पर दौड़ें

command=(eval "echo 'Hello world.';sleep .3")
while :;do
    waitNextSecondHires
    ${command[@]}
  done.

यह बिल्कुल वही परिणाम देना चाहिए।

काम देता है समारोह " repeat" के रूप में अनुरोध:

आप इसे स्रोत कर सकते हैं:

mapfile  </proc/timer_list _timer_list
for ((_i=0;_i<${#_timer_list[@]};_i++));do
    ((_c+=${#_timer_list[_i]}))
    [[ ${_timer_list[_i]} =~ ^now ]] && TIMER_LIST_READ=$_c
    [[ ${_timer_list[_i]} =~ offset:.*[1-9] ]] && \
        TIMER_LIST_OFFSET=${_timer_list[_i]//[a-z.: ]} && \
        break
done
unset _i _timer_list _c
readonly TIMER_LIST_OFFSET TIMER_LIST_READ

repeat_hires () {
    local repeat_times=$1 repeat_delay=$2 repeat_foo repeat_sleep repeat_count
    read -t .0001 repeat_foo
    if [ $? = 1 ] ;then
        repeat_sleep() { sleep $1 ;}
    else
        repeat_sleep() { read -t $1 repeat_foo; }
    fi
    shift 2
    printf -v repeat_delay "%.9f" $repeat_delay
    repeat_delay=${repeat_delay//.}
    read -N$TIMER_LIST_READ nsnow </proc/timer_list
    nsnow=${nsnow%% nsec*}
    started=${nsnow##* }
    while ((repeat_times)); do
        ((repeat_times=repeat_times>0?repeat_times-1:repeat_times))
        "${@}"
        ((repeat_times)) && ((10#$repeat_delay)) && {
            read -N$TIMER_LIST_READ nsnow </proc/timer_list
            nsnow=${nsnow%% nsec*}
            nsnow=${nsnow##* }
            (( (nsnow - started) / 10#$repeat_delay - repeat_count++ )) &&
                printf >&2 "WARNING: Command '%s' too long for %f delay.\n" \
                           "${*}" ${repeat_delay:0:${#repeat_delay}-9
                           }.${repeat_delay:${#repeat_delay}-9}
            printf -v sleep "%010d" $((
                10#$repeat_delay - ( ( nsnow - started ) % 10#$repeat_delay ) ))
            repeat_sleep ${sleep:0:${#sleep}-9}.${sleep:${#sleep}-9}
        }
    done
}

फिर इसे आज़माएं:

time repeat_hires 21 .05 sh -c 'date +%s.%N;sleep .01'
1480867565.152022457
1480867565.201249108
1480867565.251333284
1480867565.301224905
1480867565.351236725
1480867565.400930482
1480867565.451207075
1480867565.501212329
1480867565.550927738
1480867565.601199721
1480867565.651500618
1480867565.700889792
1480867565.750963074
1480867565.800987954
1480867565.853671458
1480867565.901232296
1480867565.951171898
1480867566.000917199
1480867566.050942638
1480867566.101171249
1480867566.150913407

real    0m1.013s
user    0m0.000s
sys     0m0.016s

time repeat_hires 3 .05 sh -c 'date +%s.%N;sleep .05'
1480867635.380561067
WARNING: Command 'sh -c date +%s.%N;sleep .05' too long for 0.050000 delay.
1480867635.486503367
WARNING: Command 'sh -c date +%s.%N;sleep .05' too long for 0.050000 delay.
1480867635.582332617

real    0m0.257s
user    0m0.000s
sys     0m0.004s

read -tएक अंतर्निहित है , जबकि sleepनहीं है। यह सीमा प्रभाव (यानी [कुंजी: वापसी] चुपचाप नींद को बाधित कर सकता है), लेकिन यह परीक्षण द्वारा इलाज किया जा सकता है$foo
एफ। होरी

बहुत प्रभावशाली जवाब
gena2x

4

इस (बश) को आज़माने की परवाह?

forever ()   {
    TIMES=shift;
    SLEEP=shift;
    if [ "$TIMES" = "-1" ]; then  
        while true;
        do 
            $@
            sleep $SLEEP
        done
    else
        repeat "$TIMES" $@ 
    fi; }

मैं शेल में गर्म नहीं हूं, इसलिए सुधार का स्वागत है। और मुझे अपने डिस्ट्रो में "रिपीट" कमांड नहीं लगता।

2
repeatcsh और tcsh के लिए विशिष्ट है।
कीथ थॉम्पसन

2
@KeithThompson: और zsh
थोर

4

पर्ल

#!/usr/bin/env perl
# First argument is number of seconds to sleep between repeats, remaining
# arguments give the command to repeat forever.

$sleep = shift;
$cmd = join(' ', @ARGV);

while(1) {
  system($cmd);
  sleep($sleep); 
}

4

बैश और इसके कुछ प्रकार के खोलों में सुविधाजनक (( ... ))संकेतन है, जिसमें अंकगणितीय अभिव्यक्तियों का मूल्यांकन किया जा सकता है।

तो आपकी तीसरी चुनौती के जवाब के रूप में, जहां दोनों रिपीट गिनती और प्रत्येक रिपीट के बीच देरी को कॉन्फ़िगर किया जाना चाहिए, इसे करने का एक तरीका यहां है:

repeat=10
delay=1

i=0
while (( i++ < repeat )); do
  echo Repetition $i
  sleep $delay
done

यह उत्तर कीथ के उत्तर में कवर किए गए समय के बहाव से भी ग्रस्त है ।


यह सबसे अच्छा था।
अहमद ऐव

3

जैसा कि gbrandt द्वारा उल्लेख किया गया है, यदि watchकमांड उपलब्ध है, तो निश्चित रूप से इसका उपयोग करें। हालांकि, कुछ यूनिक्स सिस्टमों ने इसे डिफ़ॉल्ट रूप से स्थापित नहीं किया है (कम से कम वे नहीं करते हैं जहां मैं काम करता हूं)।

यहाँ थोड़ा अलग सिंटैक्स और आउटपुट के साथ एक और समाधान है (BASH और SH में काम करता है):

while [ 1 ] ; do
    <cmd>
    sleep <x>
    echo ">>>>>>>>>>>>>" `date` ">>>>>>>>>>>>>>"
done

संपादित करें: मैंने कुछ हटा दिए "।" अंतिम प्रतिध्वनि में ... मेरे पर्ल दिनों से पकड़;)


3
while [ 1 ]केवल इसलिए काम करता है क्योंकि 1 को एक स्ट्रिंग के रूप में माना जाता है, जैसे while [ -n 1 ]while [ 0 ]या while [ jeff ]यही काम करेगा। while trueबहुत अधिक समझ में आता है।
मिकेल

3

यदि आपका इरादा आपकी स्क्रीन पर एक संदेश प्रदर्शित करने का नहीं है, और यदि आप मिनटों में काम को दोहराने में सक्षम हो सकते हैं, तो कोंट्रेब , शायद, आपका सबसे अच्छा उपकरण होगा। उदाहरण के लिए, यदि आप हर मिनट अपने आदेश को निष्पादित करना चाहते हैं, तो आप अपनी crontabफ़ाइल में ऐसा कुछ लिखेंगे :

* * * * * my_precious_command

कृपया आगे के उदाहरण के लिए ट्यूटोरियल देखें। इसके अलावा, आप Crontab कोड जनरेटर का उपयोग करके आसानी से समय निर्धारित कर सकते हैं ।


3

अगर हम दोनों होते तो क्या होता?

यहां यह विचार है: केवल "अंतराल" के साथ, यह हमेशा के लिए दोहराता है। "अंतराल" और "समय" के साथ, यह कई बार दोहराता है, "अंतराल" द्वारा अलग किया जाता है।

उपयोगितायें :

$ loop [interval [times]] command

तो, एल्गोरिथ्म होगा:

  • सामग्री सूचीबद्ध करें
  • यदि $ 1 में केवल अंक होते हैं, तो यह अंतराल (डिफ़ॉल्ट 2) है
  • यदि $ 2 में केवल अंक होते हैं, तो यह समय की संख्या है (डिफ़ॉल्ट अनंत)
  • जबकि इन मापदंडों के साथ लूप
    • नींद "अंतराल"
    • यदि कई बार दिया गया है, तब तक एक var को घटाएँ जब तक कि वह पहुँच न जाए

इसलिए:

loop() {
    local i=2 t=1 cond

    [ -z ${1//[0-9]/} ] && i=$1 && shift
    [ -z ${1//[0-9]/} ] && t=$1 && shift && cond=1
    while [ $t -gt 0 ]; do 
        sleep $i
        [ $cond ] && : $[--t]
        $@
    done
}

नोट: यह फ्लोट्स के साथ काम नहीं करता है, इसके बावजूद sleepउन्हें स्वीकार नहीं करता है।
22:11 पर बैन किया गया

2

मैं घाव के जवाब पर एक प्रकार का निर्माण कर रहा हूं। उसके साथ आपको पहले पुनरावृत्ति के लिए एक्स सेकंड इंतजार करना पड़ा, मैं भी अपने अग्रभूमि में दौड़ रहा हूं।

./foo.sh;while sleep 1; do (./foo.sh) ; done

1

बूट करने के लिए त्वरित, गंदे और शायद खतरनाक, लेकिन अगर आप साहसी हैं और जानते हैं कि आप क्या कर रहे हैं, तो इसे repeat.shऔर chmod 755इसे डालें ,

while true
do 
    eval $1 
    sleep $2 
done

इसके साथ आह्वान करें ./repeat.sh <command> <interval>

मेरी स्पाइडी सेंस कहती है कि यह शायद ऐसा करने का एक गलत तरीका है, क्या मेरी स्पाइडी सेंस सही है?


8
Eval !? किस लिए? sleep $1; shift; "$@"या इससे बेहतर होगा।
मिकेल

दुन्नो यह -2 क्यों है। eval overkill हो सकता है ... सिवाय इसके कि आपको कब जरूरत पड़े। Eval आपको कमांड लाइन पर पुनर्निर्देशन जैसी चीजें प्राप्त करने देता है।
जोहान

1

आप init से स्क्रिप्ट चला सकते हैं (/ / / / inittab के लिए एक पंक्ति जोड़कर)। इस स्क्रिप्ट को आपके आदेश को चलाना चाहिए, उस समय के लिए सोना चाहिए जब तक आप स्क्रिप्ट को फिर से चलाने के लिए इंतजार करना चाहते हैं, और उससे बाहर निकलें। बाहर निकलने के बाद फिर से आपकी स्क्रिप्ट शुरू हो जाएगी।


1

एक मिनट से भी कम अंतराल (20 सेकंड के उदाहरण) के साथ क्रॉस्टब से नौकरी दोहराने का आसान तरीका:

crontab: * * * * * script.sh

script.sh:

#!/bin/bash
>>type your commands here.

sleep 20
>>retype your commands here.

sleep 20
>>retype your commands here.

1

आप शेल से अजगर इंटरप्रेटर से शक्ति प्राप्त कर सकते हैं।

python3 -c "import time, os
while True:
    os.system('your command')
    time.sleep(5)

आप की तरह किसी भी समय (सेकंड) में पांच बदलें।

ध्यान दें: शेल में इनपुट वापस करने के लिए SHIFT + ENTER का उपयोग करें। और लूप में प्रत्येक पंक्ति में 4 स्पेस इंडेंट टाइप करना न भूलें ।


ध्यान दें कि pythonके os.system()कमांड लाइन व्याख्या करने के लिए एक खोल निष्पादित करता है, तो लागू pythonचलाने के लिए एक कमांड समय-समय पर थोड़ा overkill है एक पाश में गोले चलाने के लिए। आप शेल में सब कुछ कर सकते हैं।
स्टीफन चेजलस

मैं आपसे सहमत हुँ। हालाँकि, प्रत्येक लूप में वर्णित 5 सेकंड की नींद है। इस प्रकार एक नया खोल शुरू करने से अतिरिक्त लागत को नजरअंदाज किया जा सकता है। यदि यह लागत अपेक्षा से अधिक लंबी हो जाती है, तो आप आवश्यकता के अनुसार कुछ नींद के समय को कम कर सकते हैं।
pah8J '

0

यह समाधान MacOSX 10.7 में काम करता है। यह अद्भुत रूप से काम करता है।

bash -c 'while [ 0 ]; do \
      echo "I will not automate this punishment in absurdum."; done'

मेरे मामले में

bash -c 'while [ 0 ]; do ls; done'

या

bash -c 'while [ 0 ]; do mv "Desktop/* Documents/Cleanup"; done'

मेरे डेस्कटॉप को लगातार साफ करने के लिए।


1
क्या आपका मतलब sleepवहां कमांड रखना है ?
कीथ थॉम्पसन

4
while [ 0 ]एक अनंत लूप लिखने का एक अजीब तरीका है; यह काम करता है क्योंकि testकमांड (जिसे भी जाना जाता है [) गैर-रिक्त स्ट्रिंग को सही मानता है। while : ; do ... ; doneअधिक मुहावरेदार है, या यदि आप चाहें तो उपयोग कर सकते हैं while true ; do ... ; done
कीथ थॉम्पसन

0

आप इस पुनरावर्ती कार्य को स्रोत कर सकते हैं:

#!/bin/bash
ininterval () {
    delay=$1
    shift
    $*
    sleep $delay
    ininterval $delay $*
}

या जोड़ें:

ininterval $*

और स्क्रिप्ट को कॉल करें।


0

कंसोल विंडो में कमांड को बार-बार चलाने के लिए मैं आमतौर पर कुछ इस तरह से चलाता हूं:

while true; do (run command here); done

यह कई कमांड के लिए भी काम करता है, उदाहरण के लिए, कंसोल विंडो में लगातार अपडेट होने वाली घड़ी प्रदर्शित करने के लिए:

while true; do clear; date; sleep 1; done


क्यों होता है पतन? आप देख सकते हैं कि यह एक काम कर रहा है उदाहरण के लिए एक टर्मिनल विंडो में कॉपी और पेस्ट करके काम कर रहा है।
थॉमस ब्राट

मुझे लगता है कि आप मतदान से नीचे उतर गए क्योंकि यह थोड़ा खतरनाक है और सीपीयू का उपभोग करता है।
ओब्ब्लास

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

साथ zshऔर एक sleepकार्यान्वयन है कि फ्लोटिंग प्वाइंट तर्क स्वीकार करता है:

typeset -F SECONDS=0 n=0
repeat 100 {cmd; sleep $(((n+=3) - SECONDS))}

या इसके लिए forever:

for ((;;)) {cmd; sleep $(((n+=3) - SECONDS))}

अपने तो sleepतैरता का समर्थन नहीं करता, तो आप हमेशा यह एक आवरण के आसपास के रूप में फिर से परिभाषित कर सकते हैं zsh's zselectbuiltin:

zmodload zsh/zselect
sleep() zselect -t $((($1 * 100) | 0))

-1

... मुझे आश्चर्य है कि इस समस्या को हल करते समय कितना जटिल समाधान बनाया जा सकता है।

यह इतना आसान हो सकता है ...

open /etc/crontab 

वहाँ फ़ाइल के अंत में 1 अगली पंक्ति रखो जैसे:

*/NumberOfSeconds * * * * user /path/to/file.sh

यदि आप हर 1 सेकंड में कुछ चलाना चाहते हैं, तो बस वहाँ रखें:

*/60 * * * * root /path/to/file.sh 

where that file.sh could be chmod 750 /path/to/file.sh

और उस file.sh के अंदर होना चाहिए:

#!/bin/bash 
#What does it do
#What is it runned by

your code or commands

और बस यही!

का आनंद लें!


6
यह सही नहीं है। * (60 प्रत्येक 60 मिनट, और * / 5, उदाहरण के लिए, प्रत्येक 5 मिनट पर चलने वाला है।
मिका

1
सेकेंड पर सेकंड की अनुमति नहीं है
GAD3R

गलत गंदगी का जवाब देने से पहले अपने सामान का परीक्षण करें।
sjas

-1
until ! sleep 60; do echo $(date); command; command; command; done

मेरे लिये कार्य करता है।

  1. मुझे इसकी हर 60 सेकंड में जरूरत नहीं है
  2. "घड़ी" सभी सिस्टम पर कमांड नहीं देखता है
  3. "वॉच" केवल एक कमांड (या स्क्रिप्ट फ़ाइल) ले सकता है
  4. नींद को शरीर के बजाय स्थिति में डालने से लूप बेहतर रूप से बाधित हो जाता है (इसलिए स्टैकओवरफ्लो के समान प्रश्न के उत्तर में दावा। दुर्भाग्य से मैं इसे फिलहाल पा सकता हूं)
  5. मैं देरी से पहले एक बार इसे निष्पादित करना चाहता हूं, इसलिए मैं समय के बजाय इसका उपयोग करता हूं

मैंने अभी देखा कि "जब तक" जाहिरा तौर पर पहले पुनरावृत्ति से पहले नींद को निष्पादित करता है। क्या पाश में छोर पर स्थिति को लगाने का कोई तरीका है?
टाइटस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.