සෑම තත්පර x කට වරක් යුනික්ස් විධානයක් සදහටම නැවත කරන්න


508

බිල්ට්-යුනික්ස් විධානයක් ඇත, 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 ක පර්ල් හෝ පයිතන් පිටපතක් වගේ, නමුත් සමහර විට මෙය කිරීමට වඩා සම්මත ක්‍රමයක් තිබේ. එසේ නොවේ නම්, ඔබේ ප්‍රියතම ස්ක්‍රිප්ටින් භාෂාවෙන් විසඳුමක් පළ කිරීමට නිදහස් වන්න.

PS: සමහර විට මෙය කිරීමට වඩා හොඳ ක්‍රමයක් 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 time] [-n number] විධානය [args ...] නැවත කරන්න?
ජොනතන් ලෙෆ්ලර්

17
සිසිල්. අවාසනාවකට මෙන් මගේ උබුන්ටු හා මගේ AIX දෙදෙනාම නැවත වේ සොයාගත නොහැකි විධාන . ඔබට එය කළ හැකි type repeatඅතර මට පැමිණෙන්නේ කොහෙන්දැයි මට දන්වන්න පුළුවන්ද?

3
මමත් උබුන්ටු වල සිටිමි. මෙය ස්ථාපනය කරන්නේ කෙසේද යන්න පිළිබඳ ඕනෑම තොරතුරක් ප්‍රයෝජනවත් වනු ඇත.
රොරි

7
repeatයනු csh සහ tcsh වලින් සාදන ලද විධානයකි.
කීත් තොම්සන්

2
E කීත් තොම්සන්, csh, tcsh සහ zsh . එය බිල්ඩින් එකකට වඩා යතුරු පදයක් වුවද
ස්ටෙෆාන් චසෙලාස්

Answers:


650

watchවිධානය උත්සාහ කරන්න .

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

ඉතින් එතකොට:

watch -n1  command

සෑම දෙවන (හොඳින්, තාක්ෂණික, සෑම එක් දෙවන ප්ලස් ඒ සඳහා ගතවන කාලය මෙම විධානය ක්රියාත්මක වනු ඇත commandලෙස ලකුණු කිරීමට watch(අවම වශයෙන් procpsහා busyboxයන්තම් ලකුණු දෙකක් අතර එක් දෙවන පිරිහිමට පත් නිර්මාණයන්) command) සදාකල්.

execඒ වෙනුවට විධානය ලබා දීමට ඔබට අවශ්‍ය නම් sh -c, -xවිකල්පය භාවිතා කරන්න :

watch -n1 -x command

මැකෝස් මත, ඔබට මැක් පෝර්ට්ස්watch වෙතින් ලබා ගත හැකිය :

port install watch

නැතහොත් ඔබට එය හෝම්බ rew වෙතින් ලබා ගත හැකිය :

brew install watch

2
ඔබට එය ස්ථාපනය කිරීමට මැක්පෝර්ට්ස් භාවිතා කළ හැකිය. sudo port install watch

10
හෝම්බ rew වලින් ද ලබා ගත හැකිය (බීර ස්ථාපනය කිරීමේ ඔරලෝසුව).
ලයිල්

28
+1 නව ප්‍රබල මෙවලමක් සඳහා. මම ඉස්සර while true; do X; sleep Y; done- මේක වඩා හොඳයි.
ඇඩම් මාතාන්

8
මෙම මෙවලම සමඟ ඇති ගැටළුව (අවම වශයෙන් උබුන්ටු වල) එය පූර්ණ තිරයට බල කිරීම, එබැවින් මම වරින් වර තොරතුරු දමන්නේ නම්, පෙර තොරතුරු මට අහිමි වේ.
scorpiodawg

4
එය cmdwatchFreeBSD (වරාය වලින් :) ලෙස හැඳින්වේ sysutils/cmdwatch.
ඕකි

258

බාෂ්

while+ sleep:

while true
do 
    echo "Hi"
    sleep 1
done

කෙටිමං එක්-ලයිනර් එකකට සමාන දෙයක් මෙන්න (පහත දැක්වෙන අදහස් වලින්):

while sleep 1; do echo "Hi"; done

භාවිතා ;කිරීම, විධාන සහ භාවිතා වෙන් කිරීමට sleep 1සඳහා whileඑය සෑම විටම සැබෑ නැවත පටන් ටෙස්ට්. ඔබට තවත් විධාන ලූපයට දැමිය හැකිය - ඒවා සමඟ වෙන් කරන්න;


2
මම විශ්වාස කරන්නේ එය සාමාන්‍ය බෝර්න් කවචයක ලියා ඇති ආකාරයටම ක්‍රියාත්මක වන බවයි.
dmckee --- හිටපු උපපරිපාලක පූස් පැටවා

5
ree ඩ්‍රීව්ස්, ";" බෙදුම්කරු ලෙස, විධාන තනි පේළියකින් ක්‍රියාත්මක කළ හැකිය. ටූනිගේ පිළිතුර උදාහරණයක් ලෙස බලන්න
bbaja42

59
නින්ද 1 සැමවිටම සත්‍ය වන බැවින් ඔබට එය කාල කොන්දේසිය ලෙස භාවිතා කළ හැකිය. ලෝකයේ වඩාත්ම කියවිය හැකි දේ නොව නියත වශයෙන්ම නීත්‍යානුකූල ය: නින්ද 1 අතර; do echo "හායි"; අවසන්
ඩේවිඩ් කොස්ටා

3
@David කොස්තා: ඔබ සාධාරණ කළ කරුණ, නමුත් sleepනැත සෑම විටම සැබෑ ආපසු යන්න. Such එවැනි ලූප භාවිතා කර ඇත (දිගු ප්‍රමාදයකින් වුවද), මන්ද නින්දේ ක්‍රියාවලිය killing ාතනය කිරීමෙන් එය මනාව අවසන් කිරීමට ක්‍රමයක් ඇති බැවිනි.
Incnis Mrsi

2
NIncnisMrsi මම ඒ ගැන නොසිතුවෙමි, එය ඇත්ත වශයෙන්ම ශුන්‍යය ලබා දෙන්නේ කාලය ගත වූ විට සහ ශුන්‍ය නොවන එය සං by ාවකින් අවසන් වූ විට පමණි. එය පෙන්වා දීමට ස්තූතියි
ඩේවිඩ් කොස්ටා

77

මෙය වෙනත් while+sleepපිළිතුරු වල කෙටි අනුවාදයක් පමණි , ඔබ ඔබේ දෛනික චර්යාව ලෙස බොහෝ විට මෙවැනි කාර්යයන් කරන්නේ නම්, මෙය භාවිතා කිරීමෙන් අනවශ්‍ය යතුරු එබීම් වලින් ඔබව ගලවා ගනු ඇත, සහ ඔබේ විධාන රේඛාව දිගු අවබෝධයක් ලබා ගැනීමට පටන් ගන්නේ නම් මෙය ටිකක් පහසු වේ. නමුත් මෙය ආරම්භ වන්නේ පළමුව නිදා ගැනීමෙනි.

ඔබට යමක් අනුගමනය කිරීමට අවශ්‍ය නම් මෙය සාමාන්‍යයෙන් ප්‍රයෝජනවත් වන්නේ යන්ත්‍ර පැටවීම වැනි එක්-පේළියේ ප්‍රතිදානයක් ඇත:

while sleep 1; do uptime; done

ඔව්. මෙය UUOC අසල ලේඛනගත කළ යුතුය.
ජොහාන්

11
ඔබට එය "ඔරලෝසුව" මෙන් ක්‍රියාත්මක වීමට අවශ්‍ය නම් ඔබට කළ හැකියwhile clear; do date; command;sleep 5; done
ජොහාන්

වාව්, while sleepසංයෝජනයට ස්තූතියි, යතුරු පුවරු ඉතිරි කරයි!
ජෝර්ජ් වයි.

47

මෙතෙක් පළ කර ඇති සියලුම පිළිතුරු වලට ඇති එක් ගැටළුවක් නම් විධානය ක්‍රියාත්මක වන වේලාව ප්ලාවනය වීමයි. උදාහරණයක් ලෙස, ඔබ 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?)
}


2
ප්ලාවිතය අවම කිරීම සඳහා සරලයි (නින්දේ විධානය හේතුවෙන් එය ඉතා දිගු භාවිත කවුළු හරහා ගමන් කළ හැකි අතර එහි කුඩා ක්‍රියාත්මක කාලය සමුච්චය වේ): while :; do sleep 1m & command; wait; done
ගණිතය

1
ගණිතය: දක්ෂයි. වත්මන් කවචයේ වෙනත් පසුබිම් ක්‍රියාවලියක් තිබේ නම් එය ක්‍රියා නොකරයි (ඒවා waitසියල්ලම බලා සිටිනු ඇත). ඒ වෙනස් කිරීම මගින් නිසා එතැන තියෙන්නේ waitකිරීමට wait $!, කොහෙද $!මේ වන PID වේ sleepක්රියාවලිය. මෙය පිළිතුරක් ලෙස පළ කරන්න, මම එය ඉහළට ඔසවන්නෙමි. නමුත් එය අන්තර්ක්‍රියාකාරී කවචයක බාහිර නිමැවුම් නිපදවයි.
කීත් තොම්සන්

34

මම හිතන්නේ මෙතෙක් ලබා දී ඇති සියලුම පිළිතුරු එක්කෝ ඕනෑවට වඩා තදින් බැඳී ඇත, නැතහොත් වෙනත් ප්‍රශ්නයකට පිළිතුරු දෙන්න:

  • "වැඩසටහන නැවත නැවත ක්‍රියාත්මක කරන්නේ කෙසේද, එවිට වැඩසටහන අවසන් වූ විට තත්පර X ප්‍රමාදයක් ඇති වන අතර ඊළඟ ආරම්භය" .

ඇත්තම ප්‍රශ්නය වූයේ:

  • "සෑම තත්පර 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පිටුව යෝජනා කරන පරිදි මෙය විසඳිය හැකි වුවද, ප්‍රති result ලය සමාන වේ.

අපේක්ෂිත කාර්යය ඉටු කිරීම සඳහා පහසු ක්‍රමයක්, යම්කිසි ස්පර්ශයක් නම්, පසුබිම තුළ විධානය ක්‍රියාත්මක කිරීමයි. වෙනත් විදිහකින්:

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

ඒ සඳහා ඇත්තේ එපමණකි.

ඔබට සෑම එම්එස් 500 ක් සමඟ එය ධාවනය කළ හැකිය sleep 0.5, නැතහොත් ඔබ සතුව ඇත්තේ කුමක්ද?


1
විවිධ පිළිතුරු මත ඡන්දය දුන් අයට, ඔබේ පිළිතුරේ අලංකාරය තේරෙන්නේ නැත ...
සර්ජ් ස්ට්‍රෝබෑන්ඩ්

1
ඔබේ වැඩසටහනට අතුරු ආබාධ නොමැති නම් මෙය හොඳයි. වැඩසටහනට පරතරයට වඩා වැඩි කාලයක් ගත වුවහොත්, අතුරු ආබාධවලට බාධා ඇති විය හැකිය (ගොනුවක් නැවත ලිවීම වැනි). වැඩසටහන වෙනත් දෙයක් බලාපොරොත්තුවෙන් සිටී නම් සහ වෙනත් දෙයක් සදහටම ගත වේ නම්, ඔබ වැඩි වැඩියෙන් පසුබිම් රැකියා දින නියමයක් නොමැතිව ආරම්භ කරයි. ප්‍රවේශමෙන් භාවිතා කරන්න.
ජොසෆින් මොලර්

6
වරකට එකකට වඩා නොඅඩු බව සහතික කිරීම සඳහා පසුබිම් අනුපිළිවෙල වෙනස් කළ හැකිය ./foo.sh වරකට ධාවනය වන නමුත් තත්පරයට 1 ට වඩා වේගවත් නොවේ: while :; do sleep 1 & ./foo.sh; wait; done
ගණිතය

1
ඔව්, එය එක් එක් ලූපයේ මිලි තත්පර කිහිපයක් ගසාගෙන යනු ඇත, නමුත් එය එසේ වනු ඇත. date +"%H:%M:%S.%N"එක් එක් ලූපය මත භාගය සෙමින් වැඩි වන්නේ කෙසේදැයි බැලීමට foo.sh වලින් සාදන්න .
අයිසැක්

ඔව්, බොහෝ පිළිතුරු වචනාර්ථයෙන් ප්‍රශ්නයට ආමන්ත්‍රණය නොකරන බව සත්‍යයකි . නමුත් OP ට අවශ්‍ය දේට ඔවුන් පිළිතුරු දීම පාහේ ආරක්ෂිත ඔට්ටුවකි. මෙම විශ්රාම වැටුප් ඇත්තටම පිළිතුරක් පිළිගෙන ඇත නම් එය ආරක්ෂිත ඔට්ටු වනු ඇත ... ඒත් මේක හොඳයි, ලබා ඔබට හැකි අතුරු ආබාධ දන්නවා සහ ඔබ එම විධානය පිළිබඳ සාමාන්ය ලකුණු කාලය චක්රය කාලය ඉක්මවා යන්නේ නැති බව නිශ්චිත ය
අවුස්පෙක්ස්

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"බැක්ටික්ස් (`) වලින් වට වූ" ඕනෑම "විධානයකින් ප්‍රතිස්ථාපනය කළ හැකි ස්ථානය .

විරාමයක් සඳහා, sleepfor loop සඳහා ප්‍රකාශයක් එක් කරන්න :

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.
මයිකල්

6
Ik මයිකල්: හෝ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
නිහ ly

ඉතා ආකර්ෂණීය පිළිතුර
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
E කීත් තොම්සන්: සහ 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

ඔබේ අභිප්‍රාය ඔබේ තිරයට පණිවිඩයක් ප්‍රදර්ශනය නොකිරීම සහ මිනිත්තු ගණන අනුව ඔබට එම කාර්යය නැවත කිරීමට හැකි නම්, ක්‍රොන්ටාබ් , සමහර විට ඔබේ හොඳම මෙවලම වනු ඇත. උදාහරණයක් ලෙස, සෑම විනාඩියකටම ඔබේ විධානය ක්‍රියාත්මක කිරීමට අවශ්‍ය නම්, ඔබ ඔබේ crontabගොනුවේ මේ වගේ දෙයක් ලියයි :

* * * * * my_precious_command

වැඩි විස්තර සඳහා කරුණාකර නිබන්ධනය බලන්න. එසේම, ඔබට ක්‍රොන්ටාබ් කේත උත්පාදක යන්ත්රය භාවිතයෙන් වේලාවන් පහසුවෙන් සැකසිය හැකිය .


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

අපි දෙදෙනාම සිටියා නම් කුමක් කළ යුතුද?

මෙන්න අදහස: "පරතරය" සමඟ පමණක් එය සදහටම පුනරාවර්තනය වේ. "පරතරය" සහ "වේලාවන්" සමඟ, එය "වාර ගණන" මගින් වෙන් කරන ලද මෙම වාර ගණන පුනරාවර්තනය වේ.

භාවිතය:

$ 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පිළිගත්තද එය පාවෙන සමඟ ක්‍රියා නොකරයි.
බාරොන්ස්ඩ්

2

මම ස්ලොග්ගේ පිළිතුර මත ප්‍රභේදයක් නිර්මාණය කරමි. ඔහු සමඟ ඔබට පළමු පුනරාවර්තනය සඳහා තත්පර X ක් බලා සිටීමට සිදු විය, මම ද මගේ පෙරමුනේ ධාවනය කරමි.

./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
ඊවාල්!? කුමක් සඳහා ද? sleep $1; shift; "$@"හෝ ඒ හා සමාන වඩා හොඳ වනු ඇත.
මයිකල්

ඩන්නෝ ඇයි මෙය -2. eval ඕනෑවට වඩා වැඩියි ... ඔබට අවශ්‍ය විට හැර. විධාන රේඛාවට යළි හරවා යැවීම වැනි දේ ලබා ගැනීමට ඊවාල් ඔබට ඉඩ දෙයි.
ජොහාන්

1

ඔබට init වෙතින් ස්ක්‍රිප්ට් එකක් ධාවනය කළ හැකිය (/ etc / 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 SPACE ඉන්ඩෙන්ට් ටයිප් කිරීමට අමතක නොකරන්න .


බව සටහන pythonගේ os.system()ඉටු විධාන රේඛාවේ අර්ථ නිරූපණය කිරීමට තිබෙන shell, ඒ නිසා කැඳවමින් 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


පහත වැටීම ඇයි? උදාහරණය ටර්මිනල් කවුළුවකට පිටපත් කර ඇලවීමෙන් මෙය ක්‍රියාකාරී විසඳුමක් බව ඔබට පෙනේ.
තෝමස් බ්‍රැට්

මම හිතන්නේ ඔබ ඡන්දය පාවිච්චි කළේ එය ටිකක් භයානක නිසාත්, CPU පරිභෝජනය කරන නිසාත් ය.
ojblass

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ගේ 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
crontab හි
තත්පරයට

වැරදි ජරාවක් සමඟ පිළිතුරු දීමට පෙර ඔබේ දේවල් පරීක්ෂා කරන්න.
sjas

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

මට වැඩ කරයි.

  1. සෑම තත්පර 60 කටම මට එය අවශ්‍ය නොවේ
  2. "watch" සියලු පද්ධතිවල විධාන නරඹන්නේ නැත
  3. "watch" ට ගත හැක්කේ එක් විධානයක් පමණි (හෝ ස්ක්‍රිප්ට් ගොනුවක්)
  4. ශරීරය වෙනුවට නින්දේ තත්වය තැබීමෙන් ලූපය වඩා හොඳ බාධා ඇති වේ (එබැවින් ස්ටක් ඕවර් ප්‍රවාහය පිළිබඳ සමාන ප්‍රශ්නයකට පිළිතුරු වශයෙන් හිමිකම් පෑමක්. අවාසනාවකට මට එය මේ මොහොතේ සොයාගත හැකිය)
  5. ප්‍රමාදයට පෙර එක් වරක් එය ක්‍රියාත්මක කිරීමට මට අවශ්‍යය, එබැවින් මම කාලය වෙනුවට භාවිතා කරමි

පළමු පුනරාවර්තනයට පෙර "තෙක්" නින්ද ක්‍රියාත්මක කරන බව මම දුටුවෙමි. ලූපය අවසානයේ තත්වය බැෂ් කිරීමට ක්‍රමයක් තිබේද?
ටයිටස්
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.