x 초마다 유닉스 명령을 영원히 반복하십시오


480

repeat첫 번째 인수가 명령을 반복하는 횟수 인 내장 Unix 명령 이 있습니다. 여기서 인수는 명령이 나머지 인수에 의해 지정됩니다 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 줄 Perl 또는 Python 스크립트와 같다는 것을 알고 있지만 더 표준적인 방법이있을 수 있습니다. 그렇지 않은 경우 Rosetta Stone 스타일 의 선호하는 스크립팅 언어로 솔루션을 게시하십시오 .

추신 : 아마도이 작업을 수행하는 더 좋은 방법 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 ...]를 반복 하시겠습니까?
Jonathan Leffler

17
시원한. 불행히도 내 우분투와 AIX 반복 에서 명령을 찾을 수 없습니다 . 당신은 할 수있는 type repeat날이 어디에서오고 알려주세요?

3
나는 또한 우분투에 있고 반복 설치가 없습니다. 이것을 설치하는 방법에 대한 정보가 도움이 될 것입니다.
Rory

7
repeatcsh 및 tcsh에 내장 된 명령입니다.
Keith Thompson

2
@KeithThompson, csh, tcsh 및 zsh 입니다. 그것은 더는 내장보다 키워드 비록
스테판 Chazelas가

답변:


615

watch명령을 시도하십시오 .

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

그래서:

watch -n1  command

(매초, 기술적으로는 1 초마다 (적어도 구현 과 ) command실행 하는 데 걸리는 시간 과 두 개의 실행 사이에서 1 초간 잠자기 ) 명령을 영원히 실행 합니다.watchprocpsbusyboxcommand

exec대신에 명령을 전달 sh -c하려면 -xoption을 사용하십시오 .

watch -n1 -x command

macOS에서는 Mac 포트watch 에서 얻을 수 있습니다 .

port install watch

또는 Homebrew 에서 얻을 수 있습니다 .

brew install watch

2
MacPorts를 사용하여 설치할 수 있습니다. sudo port install watch

10
홈브류 (Brew Install Watch)에서도 사용 가능합니다.
Lyle

28
+1 새로운 강력한 도구입니다. 나는 예전부터 while true; do X; sleep Y; done-더 나아졌다.
Adam Matan

4
이 도구의 문제 (적어도 우분투에서)는 전체 화면을 강제로 수행하므로 주기적 정보를 덤프하면 이전 정보가 손실됩니다.
scorpiodawg

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항상 true를 반환하기 때문에 테스트. 루프에 더 많은 명령을 넣을 수 있습니다.;


2
나는 그것이 일반적인 Bourne 쉘로 작성된대로 작동한다고 생각합니다.
dmckee

5
";"를 사용하는 @dreeves 구분 기호로 명령을 한 줄로 실행할 수 있습니다. Toony의 답변을 예로 들어보십시오
bbaja42

56
sleep 1은 항상 true를 반환하므로 while 조건으로 사용할 수 있습니다. 세계에서 가장 읽기 쉬운 것이 아니라 절대적으로 합법적입니다 : while sleep 1; 에코 "안녕하세요"; 완료
David Costa

3
@David Costa : 당신은 합리적인 지적을했지만 항상 사실을 돌려주는 sleep것은 아닙니다 . Ī̲는 그러한 루프 (긴 지연이 있더라도)를 사용했습니다. 즉, 슬립 프로세스를 종료하여 정상적으로 종료 할 수있는 방법이 있기 때문입니다.
Incnis Mrsi

2
@IncnisMrsi 나는 그것을 생각하지 못했습니다. 시간이 지났을 때만 실제로 0을 반환하고 신호에 의해 종료되면 0이 아닌 값을 반환합니다. 지적 해 주셔서 감사합니다
David Costa

71

이것은 while+sleep일상적인 일과 같이 이러한 종류의 작업을 자주 실행하는 경우 불필요한 키 누르기를 방지하고 명령 줄이 더 오래 이해되기 시작하면 조금 더 쉬운 다른 답변 의 짧은 버전입니다 . 그러나 이것은 먼저 자고 시작합니다.

이것은 일반적으로 기계 부하와 같은 한 줄짜리 출력이 필요한 경우에 유용합니다.

while sleep 1; do uptime; done

예. 이것은 UUOC 옆에 문서화되어야합니다.
Johan

10
"시계"처럼 작동 시키려면 다음과 같이하십시오.while clear; do date; command;sleep 5; done
Johan

와우, while sleep조합에 감사드립니다 .
George Y.

45

지금까지 게시 된 모든 답변의 한 가지 문제는 명령이 실행되는 시간이 표류 할 수 있다는 것입니다. 예를 들어, sleep 10사이에 명령 을 수행하고 명령을 실행하는 데 2 ​​초가 걸리면 12 초마다 실행됩니다. 실행하는 데 가변 시간이 걸리면 장기적으로 실행 시간을 예측할 수 없습니다.

이것은 당신이 원하는 것일 수도 있습니다. 그렇다면 다른 솔루션 중 하나를 사용하거나이 솔루션을 사용하지만 sleep통화를 단순화하십시오 .

1 분 분석의 경우, 각 명령 수행 시간에 관계없이 cron 작업이 지정된 시간에 실행됩니다. (실제로 이전 크론 작업이 계속 실행중인 경우에도 새로운 크론 작업이 시작됩니다.)

다음 간격까지 대기하는 간단한 Perl 스크립트는 다음과 같습니다. 예를 들어 10 초 간격으로 명령이 12:34:00, 12:34:10, 12:34:20 등에 실행될 수 있습니다. 명령 자체는 몇 초가 걸립니다. 명령이 interval초 이상 실행되면 cron과 달리 다음 간격을 건너 뜁니다. 간격은 에포크를 기준으로 계산되므로 86400 초 (1 일) 간격은 UTC 자정에 실행됩니다.

#!/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
드리프트를 최소화하기 위해 bash에서 더 간단합니다 (sleep 명령으로 인해 매우 긴 사용 창에서 드리프트하고 bash 자체가 작은 실행 시간을 누적 할 수 있음) : while :; do sleep 1m & command; wait; done
math

1
@math : 영리합니다. 현재 셸에서 다른 백그라운드 프로세스가 실행 중이면 작동하지 않습니다 ( wait모두 대기합니다). 즉 변경하여 고칠 수 있어요 waitwait $!여기서 $!의 PID를이다 sleep과정. 이것을 답변으로 게시하면 투표하겠습니다. 그러나 대화 형 셸에서 일부 외부 출력을 생성합니다.
Keith Thompson

29

지금까지의 모든 대답이 너무 복잡하거나 다른 질문에 대답했다고 생각합니다.

  • "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

정확히 1 초마다 실행되지는 않습니다. -p플래그가 있더라도 man watch페이지에서 제안한 것처럼이 문제를 해결할 수 있지만 결과는 동일합니다.

원하는 작업을 수행하는 쉬운 방법은 백그라운드에서 명령을 실행하는 것입니다. 다시 말해:

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

그리고 그것이 전부입니다.

로 500ms마다 sleep 0.5또는 무엇을 사용할 수 있습니까?


1
다른 답변에 투표 한 사람들은 귀하의 답변의 우아함을 이해하지 못합니다 ...
Sroo Stroobandt

프로그램에 부작용이없는 한 좋습니다. 프로그램이 간격보다 오래 걸리면 파일 덮어 쓰기와 같은 부작용이 발생할 수 있습니다. 프로그램이 다른 것을 기다렸다가 다른 것이 영원히 걸리면 점점 더 많은 백그라운드 작업을 무한정 시작하게됩니다. 주의해서 사용하십시오.
John Moeller

4
한 번에 하나 이상의 ./foo.sh가 실행되도록 초당 1보다 빠르지 않도록 백그라운드 순서를 반전시킬 수 있습니다. while :; do sleep 1 & ./foo.sh; wait; done
math

예, 각 루프에서 몇 밀리 초 드리프트되지만 그럴 것입니다. date +"%H:%M:%S.%N"foo.sh에서 각 루프에서 분수가 어떻게 천천히 증가하는지 확인 하십시오.
Isaac

그렇습니다. 대부분의 답변이 문자 그대로 문제를 해결 하지는 않습니다 . 그러나 OP가 원하는 것에 응답하는 것은 거의 안전합니다. 영업 이익이 실제로 대답을 받아들 였었다 경우는 안전 내기를 할 것입니다 ...하지만 이것은 좋은 제공 당신이 부작용을 인식 하고 명령의 평균 실행 시간이 사이클 시간을 초과하지 않을 것이 확실
Auspex

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면 for 루프 안에 문장을 추가하십시오 :

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좋습니다.
Mikel

5
@Mikel : 또는while :
Keith Thompson

10

최근 리눅스 커널에서 최근 bash> = 4.2, 답변.

실행 시간을 제한하기 위해 포크없습니다 ! 내장 만 사용됩니다.

이를 위해 read대신 내장 함수를 사용 sleep합니다. 불행히도 이것은 notty 세션에서 작동하지 않습니다 .

요청 된 빠른 함수 " 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

제출 된 명령의 세분성 및 기간에 따라 ...

최근 Linux 커널에는 /proc/timer_list나노초 단위의 시간 정보가 포함 된 procfile 이 있습니다.

명령을 정확히 1 초마다 실행하려면 명령이 1 초 안에 끝나야합니다! 그리고 거기에서 현재 초의 나머지 부분sleep 만 있으면됩니다 .

지연이 더 중요하고 명령에 많은 시간이 필요하지 않은 경우 다음을 수행 할 수 있습니다.

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

그러나 세밀한 입도를 얻는 것이 목표라면 다음을 수행해야합니다.

나노초 정보를 사용하여 초가 시작될 때까지 기다립니다.

이를 위해 작은 bash 함수를 작성했습니다.

# 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그렇지 않습니다. 이것은 국경 효과 (즉, [key : return]을 누르면 수면을 조용히 중단 할 수 있음)가 될 수 있지만, 테스트를 통해 처리 할 수 ​​있습니다.$foo
F. Hauri

매우 인상적인 답변
gena2x

4

이것을 시도해보십시오 (Bash)?

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

나는 껍질에 뜨겁지 않기 때문에 개선을 환영합니다. 그리고 나는 내 배포판에 "반복"명령이없는 것 같습니다.

2
repeatcsh 및 tcsh에만 해당됩니다.
Keith Thompson

2
@KeithThompson : 및 zsh
Thor

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

이 답변은 Keith의 답변 에서 다루는 타이밍 드리프트로 인해 어려움을 겪습니다 .


이것이 최고였습니다.
Ahmad Awais

3

gbrandt가 언급했듯이 watch명령을 사용할 수 있으면 반드시 사용하십시오. 그러나 일부 유닉스 시스템은 기본적으로 설치되어 있지 않습니다 (적어도 내가 일하는 곳은 아닙니다).

구문과 출력이 약간 다른 또 다른 솔루션이 있습니다 (BASH 및 SH에서 작동).

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

편집 : "."을 제거했습니다. 마지막 반향 진술에서 ... 내 Perl 시절의 숙취;)


3
while [ 1 ]1이처럼 문자열로 취급되기 때문에 작동합니다 while [ -n 1 ]. while [ 0 ]또는 while [ jeff ]같은 일을 할 것입니다. while true훨씬 더 의미가 있습니다.
Mikel

3

화면에 메시지를 표시하지 않고 분 단위로 작업을 반복 할 여유가 있다면 crontab이 가장 좋은 도구 일 것입니다. 예를 들어, 1 분마다 명령을 실행하려면 crontab파일 에 다음과 같이 작성 하십시오.

* * * * * my_precious_command

추가 예제는 자습서를 확인하십시오. 또한 Crontab 코드 생성기를 사용하여 타이밍을 쉽게 설정할 수 있습니다 .


3

우리 둘 다 가지고 있다면 어떨까요?

아이디어는 다음과 같습니다. "간격"만 있으면 영원히 반복됩니다. "간격"및 "시간"을 사용하면 "간격"으로 구분 된이 횟수만큼 반복됩니다.

사용법 :

$ loop [interval [times]] command

따라서 알고리즘은 다음과 같습니다.

  • 목록 항목
  • $ 1에 숫자 만 포함 된 경우 간격입니다 (기본값 2).
  • $ 2에 숫자 만 포함 된 경우 횟수입니다 (기본 무한).
  • 이 매개 변수를 사용하는 동안 while 루프
    • 수면 "간격"
    • 여러 번 주어진 경우, 도달 할 때까지 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 분 37 초에 Baroned

2

swalog의 답변에 변형을 만들어 내었습니다. 그의 첫 번째 반복을 위해 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>

내 spidey 감각은 이것이 아마도 이것을하는 악한 방법이라고 말합니다. 내 spidey 감각이 맞습니까?


8
평가!? 무엇 때문에? sleep $1; shift; "$@"또는 유사한 것이 훨씬 나을 것입니다.
Mikel

Dunno 왜 이것이 -2입니까? eval은 필요할 때를 제외하고는 과잉 일 수 있습니다. 평가를 사용하면 명령 줄로 리디렉션과 같은 것을 얻을 수 있습니다.
Johan

1

init에서 스크립트를 실행할 수 있습니다 (/ etc / inittab에 행 추가). 이 스크립트는 명령을 실행하고 스크립트를 다시 실행할 때까지 대기하려는 시간 동안 휴면 한 후 종료해야합니다. 종료 후 스크립트가 다시 시작됩니다.


1

1 분 (20 초 예) 미만의 간격으로 crontab에서 작업을 반복하는 쉬운 방법 :

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)

원하는 시간 (초)에 5를 교체하십시오.

주의 : 리턴은 SHIFT + ENTER를 사용하여 쉘에 입력을 리턴합니다. 그리고 4 입력하는 것을 잊지 마세요 공간의 while 루프의 각 줄에 들여 쓰기를.


참고 python들 ' os.system()때문에 호출 명령 행을 해석하는 쉘을 실행 python명령이 주기적으로 비트 잔인한 실행하는 루프에서 쉘을 실행합니다. 쉘의 모든 것을 할 수도 있습니다.
Stéphane Chazelas

동의합니다. 그러나 각 루프에서 설명한대로 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거기 에 명령을 내렸습니까?
Keith Thompson

4
while [ 0 ]무한 루프를 작성하는 이상한 방법입니다. test명령 (이라고도 함 [)은 비어 있지 않은 문자열을 true로 처리 하기 때문에 작동 합니다. while : ; do ... ; done더 관용적이거나 선호하는 경우를 사용할 수 있습니다 while true ; do ... ; done.
Keith Thompson

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


왜 공감해야합니까? 예제를 복사하여 터미널 창에 붙여 넣어서 이것이 작동하는 솔루션임을 알 수 있습니다.
Thomas Bratt

나는 약간 위험하고 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

zshsleep부동 소수점 인수를 받아 구현 :

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

또는를위한 forever:

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

귀하의 경우 sleep수레를 지원하지 않습니다, 당신은 항상 래퍼 주위로 다시 정의 할 수 zshzselect내장 :

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 분마다 실행됩니다.
mika

1
초 crontab을 허용되지 않습니다
GAD3R

틀린 똥으로 대답하기 전에 물건을 테스트하십시오.
sjas

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

나를 위해 작동합니다.

  1. 정확히 60 초마다 필요하지 않습니다
  2. "watch"는 모든 시스템에서 명령을 감시하지 않습니다
  3. "watch"는 하나의 명령 (또는 스크립트 파일) 만 사용할 수 있습니다
  4. 신체 대신 수면 상태로두면 루프가 더 잘 인터럽트 될 수 있습니다 (따라서 stackoverflow에 대한 비슷한 질문에 대한 답변의 주장은 불행히도 현재 찾을 수 있습니다)
  5. 지연되기 전에 한 번 실행하고 싶습니다.

방금 "반복"이 첫 번째 반복 전에 슬립을 실행하는 것으로 나타났습니다. bash의 루프 끝에 조건을 넣는 방법이 있습니까?
Titus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.