유닉스 스크립트를 15 초마다 실행하는 방법은 무엇입니까?


84

나는 시계를 포함하여 몇 가지 해결책을 보았고 단순히 백그라운드에서 반복되는 (잠자기) 스크립트를 실행했지만 이상적인 것은 없었다.

15 초마다 실행해야하는 스크립트가 있고 cron이 초를 지원하지 않기 때문에 다른 것을 알아 내야합니다.

Unix에서 15 초마다 스크립트를 실행하는 가장 강력하고 효율적인 방법은 무엇입니까? 스크립트는 재부팅 후에도 실행해야합니다.


1
실행하는 데 얼마나 걸리나요?
Adam Matan 2009-06-23

답변:


77

cron을 사용하여 매분 스크립트를 실행하고 해당 스크립트가 실행 사이에 15 초의 휴면 상태로 스크립트를 4 번 실행하도록합니다.

(스크립트 실행이 빠르다고 가정합니다. 그렇지 않은 경우 절전 시간을 조정할 수 있습니다.)

이렇게하면 cron15 초의 실행 기간뿐만 아니라 모든 이점을 얻을 수 있습니다.

편집 : 아래 @bmb의 주석도 참조하십시오.


@Aiden : 하! 나의 천적, 다시 만난다!
RichieHindle 2009-06-23

56
스크립트가 실행하는 데 걸리는 시간이 일치하지 않으면 스크립트를 4 개 복사하십시오. 하나는 시작하기 15 초 전에, 다른 하나는 30 초, 다른 하나는 45 초, 다른 하나는 0입니다. 그런 다음 1 분마다 4 개를 모두 실행합니다.
bmb

@RichieHindle-두려워하지 마세요. 저는 몇 분을 초 단위로 세분화하지 않아 암살당했습니다. 하지만 난 당신을보고 있어요 : P
Aiden Bell

이 크론이 1 분마다 트리거되는 방법
DevZer0 2013 년

실제로 외부 스크립트는 내부 스크립트를 4 번이 아닌 3 번 실행해야합니다. 그렇지 않으면 마지막 1 분의 마지막 실행이 다음 1 분의 첫 실행과 겹칠 것입니다. 이것은 4 번이 아니라 매분 5 번 내부 스크립트를 실행하는 것입니다.
Tulains Córdova 2015 년

290

cron에서 스크립트를 실행해야하는 경우 :

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

스크립트 이름 및 경로를 / foo / bar / your_script로 바꿉니다.


18
이것은 매우 영리합니다. +1
SingleNegationElimination 2009-06-23

4
이것은 나를 위해 완벽하게 작동했습니다. 백그라운드 작업 사용에 대한 위의 해결책은 여러 하위 프로세스를 생성하고 메모리 문제를 일으켰습니다.
Hacknightly

2
실행 PHP 스크립트는이 작업을 수행하는 경우 :* * * * * sleep 15; php /foo/bar/your_script
ImaginedDesign

1
PHP 스크립트를 실행하는 경우는 선을 앞에 추가 할 수 있습니다 #!/usr/bin/php당신의 PHP 스크립트의 상단에 그것을 실행하기
아론 Blenkush

18
이 솔루션을 위해 Google을 검색해야하는 것이 부끄럽습니다. 아마도 stackoverflow는 나를 덜 생각하게 만듭니다.
chris finne

15

위의 수정 된 버전 :

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

13

백그라운드에서 실행하지 않습니까?

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

이것은 얻는 것만 큼 효율적입니다. 중요한 부분은 15 초마다 실행되고 스크립트는 나머지 시간 동안 휴면합니다 (따라서주기를 낭비하지 않음).


8
편집은 최소한 8 자 (멍청한 IMHO) 여야하므로 &3 행 끝에를 추가 할 수 없습니다 . 어쨌든 이것은 15 초마다 실행되지 않습니다. 이것은 "15 초 + echo hello실행하는 데 오래 걸린다 "마다 실행됩니다 . 0.01 초가 될 수 있습니다. 19 시간이 될 수 있습니다.
Parthian Shot

1

cron보다 빠르게 스케줄러를 작성했습니다. 나는 또한 중복 가드를 구현했습니다. 이전 프로세스가 아직 실행중인 경우 새 프로세스를 시작하지 않도록 스케줄러를 구성 할 수 있습니다. https://github.com/sioux1977/scheduler/wiki 에서 살펴보세요


0

nanosleep (2) 사용하십시오 . timespec나노초 정밀도로 시간 간격을 지정하는 데 사용되는 구조 를 사용합니다.

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

1
15 초마다 생성되는 것은 커널 스레드가 아니라 쉘 스크립트이기 때문에 나노초 정밀도가 필요하지 않다고 생각합니다.
Parthian Shot

@ParthianShot 어쩌면 당신은 결코 알지 못합니다.
알렉산더 Suraphel

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

이전 답변 이후로 나는 다르고 아마도 더 나은 또 다른 솔루션을 생각해 냈습니다. 이 코드를 사용하면 마이크로 초 정밀도로 1 분에 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
다시 게시하는 대신 원본을 편집하십시오!
Vogon Jeltz

-1

중복 실행을 방지하려면 해당 스레드에 설명 된 잠금 메커니즘을 사용하십시오 .


2
-1 OP는 중복 실행을 피할 필요가 있다고 말하지 않았습니다. 재진입 할 ​​수 있습니다. 또한 이것은 질문에 대한 답이 아닙니다.
Parthian Shot
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.