15 초마다 유닉스 스크립트를 실행하는 방법은 무엇입니까?
문제
나는 백그라운드에서 시계 및 단순히 루핑 (및 수면) 스크립트를 실행하는 것을 포함한 몇 가지 솔루션을 보았지만 이상적인 것은 없었습니다.
15 초마다 실행 해야하는 스크립트가 있으며 Cron은 몇 초를 지원하지 않기 때문에 다른 것을 알아 내야합니다.
UNIX에서 15 초마다 스크립트를 실행하는 가장 강력하고 효율적인 방법은 무엇입니까? 스크립트는 재부팅 후에도 실행해야합니다.
해결책
나는 Cron을 사용하여 매 순간 스크립트를 실행하고, 스크립트가 런 사이의 15 초 수면으로 스크립트를 4 번 실행하게합니다.
(스크립트가 빠르게 실행되었다고 가정합니다. 그렇지 않은 경우 수면 시간을 조정할 수 있습니다.)
그렇게하면 모든 이점을 얻습니다 cron
15 초의 실행 기간뿐만 아니라.
편집하다: 아래 @BMB의 의견도 참조하십시오.
다른 팁
Cron에서 스크립트를 실행해야한다고 주장하면 :
* * * * * /foo/bar/your_script
* * * * * sleep 15; /foo/bar/your_script
* * * * * sleep 30; /foo/bar/your_script
* * * * * sleep 45; /foo/bar/your_script
스크립트 이름 및 Path로/foo/bar/your_script로 바꾸십시오.
위의 수정 된 버전 :
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
배경에서 이것을 실행하지 않습니까?
#!/bin/sh
while [ 1 ]; do
echo "Hell yeah!" &
sleep 15
done
이것은 얻는 것만 큼 효율적입니다. 중요한 부분은 15 초마다 실행되며 스크립트는 나머지 시간 (따라서주기 낭비가 아닙니다).
나는 Cron보다 더 빨리 스케줄러를 썼습니다. 나는 또한 겹치는 가드를 구현했습니다. 이전 프로세스가 여전히 실행중인 경우 새 프로세스를 시작하지 않도록 스케줄러를 구성 할 수 있습니다. 보세요 https://github.com/sioux1977/scheduler/wiki
사용 나노 수면 (2). 구조를 사용합니다 timespec
이는 나노 초 정밀도로 시간 간격을 지정하는 데 사용됩니다.
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#! /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
이전 답변 이후로 다른 솔루션을 생각해 냈습니다. 이 코드를 사용하면 프로세스가 마이크로 초 정밀도로 분당 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
실행의 중첩 가능성을 피하려면 그 다음에 설명 된대로 잠금 메커니즘을 사용하십시오. 실.