it-swarm-ko.tech

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

내장 Unix 명령 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 줄 Perl 또는 Python 스크립트)와 비슷하지만 더 표준적인 방법이있을 수도 있지만 그렇지 않은 경우 선호하는 스크립팅 언어로 솔루션을 게시하십시오.

추신 : 아마도이 작업을 수행하는 더 좋은 방법은 repeat를 일반화하여 반복하는 횟수 (-1은 무한대를 의미 함)와 반복 사이에 잠을자는 시간 (초)을 모두 취하는 것입니다. 위의 예는 다음과 같습니다.

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

watch 명령을 시도하십시오.

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

그래서:

watch -n1  command

기술적으로, 1 초마다 (commandwatch (최소한 procpsbusybox implementations)은 command)의 두 실행 사이에서 1 초간 지속됩니다.

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

watch -n1 -x command

MacOS에서는 Mac Ports 에서 watch를 얻을 수 있습니다.

port install watch

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

brew install watch
637
Gregor Brandt

배쉬

while + sleep :

while true
do 
    echo "Hi"
    sleep 1
done

속기 원 라이너와 같은 것이 있습니다 (아래 주석에서).

while sleep 1; do echo "Hi"; done

;을 사용하여 명령을 구분하고 항상 true를 리턴하므로 while 테스트에 sleep 1을 사용합니다. 더 많은 명령을 루프에 넣을 수 있습니다. ;

255
pope

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

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

while sleep 1; do uptime; done
73
Bekir Dogan

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

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

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

다음 간격까지 대기하는 간단한 Perl 스크립트는 다음과 같습니다. 예를 들어 10 초 간격으로 명령이 12:34:00, 12:34:10, 12:34:20 등에 실행될 수 있습니다. 명령 자체는 몇 초가 걸립니다. 명령이 interval 초 이상 실행되면 cron과 달리 다음 간격을 건너 뜁니다. 간격은 Epoch를 기준으로 계산되므로 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?)
}
46
Keith Thompson

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

  • "프로그램이 완료된 시점과 다음 시작 시점 사이에 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

그리고 그게 전부입니다.

sleep 0.5로 500ms마다 실행할 수 있습니다.

33
swalog

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"는 백틱 (`)으로 둘러싸인 "any"명령으로 대체 될 수 있습니다.

그리고 잠시 멈추려면 for 루프 안에 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}'
17
Tooony

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

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

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

요청에 따라 빠른 bash 함수 "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

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

최근 리눅스 커널에는 procfile /proc/timer_list 시간 정보를 나노초로 포함합니다.

명령을 정확히 1 초마다 실행하려면 명령이 1 초 안에 끝나야합니다! And 거기에서 sleeprest ​​전류 만 둘째.

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

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.

이것은 정확히 동일한 결과를 제공해야합니다.

요청한대로 bash 함수 "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
10
F. Hauri

배쉬와 그 종류의 껍질은 편리한 (( ... )) 산술 식을 평가할 수있는 표기법.

따라서 각 반복 간의 반복 횟수와 지연을 모두 구성 할 수있는 세 번째 과제에 대한 답으로 다음과 같은 방법을 사용할 수 있습니다.

repeat=10
delay=1

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

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

4
Thor

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

* * * * * my_precious_command

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

4
Barun

#!/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
dreeves

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

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

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

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

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

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

3
bedwyr

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

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

사용법 :

$ 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]
        [email protected]
    done
}
3
Baronsed

Swalog의 답변에 변형을 만들어 내었습니다. 그의 첫 번째 반복을 위해 X 초를 기다려야 했으므로 전경에서도 실행 중입니다.

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

셸에서 python 통역사로부터 힘을 얻을 수 있습니다.

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

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

주의 : 리턴은 SHIFT + ENTER를 사용하여 쉘에 입력을 리턴합니다. while 루프의 각 줄에 4 SPACE 들여 쓰기를 입력하는 것을 잊지 마십시오.

1
pah8J

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
Charles nakhel

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

1
Roberto Paz

빠르고, 더럽고, 부팅하기에 위험 할 수 있지만, 모험심이 있고 수행중인 작업을 알고 있다면 repeat.shchmod 755에 넣으십시오.

while true
do 
    eval $1 
    sleep $2 
done

./repeat.sh <command> <interval>로 호출하십시오.

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

1
mallyone
#! /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
user56318

...이 문제를 해결할 때 얼마나 복잡한 솔루션을 만들 수 있는지 궁금합니다.

너무 쉬울 수 있습니다 ...

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

그리고 그게 전부입니다!

즐겨!

0
MIrra

부동 소수점 인수를 허용하는 zshsleep 구현의 경우 :

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

또는 forever의 경우 :

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

sleep가 float를 지원하지 않는 경우, 항상 zsh 's zselect 내장에서 래퍼로 재정의 할 수 있습니다.

zmodload zsh/zselect
sleep() zselect -t $((($1 * 100) | 0))
0
Stéphane Chazelas

이 재귀 함수를 소스로 사용할 수 있습니다.

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

또는 다음을 추가하십시오.

ininterval $*

스크립트를 호출하십시오.

0
user unknown

콘솔 창에서 명령을 반복적으로 실행하려면 일반적으로 다음과 같이 실행합니다.

while true; do (run command here); done

예를 들어 콘솔 창에 지속적으로 업데이트되는 시계를 표시하는 등 여러 명령에서도 작동합니다.

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

0
Thomas Bratt

이 솔루션은 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'

데스크탑을 지속적으로 정리합니다.

0
Dan Ruiz