나는 시계를 포함하여 몇 가지 해결책을 보았고 단순히 백그라운드에서 반복되는 (잠자기) 스크립트를 실행했지만 이상적인 것은 없었다.
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
스크립트 이름 및 경로를 / foo / bar / your_script로 바꿉니다.
* * * * * sleep 15; php /foo/bar/your_script
#!/usr/bin/php
당신의 PHP 스크립트의 상단에 그것을 실행하기
위의 수정 된 버전 :
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 초마다 실행되고 스크립트는 나머지 시간 동안 휴면합니다 (따라서주기를 낭비하지 않음).
&
3 행 끝에를 추가 할 수 없습니다 . 어쨌든 이것은 15 초마다 실행되지 않습니다. 이것은 "15 초 + echo hello
실행하는 데 오래 걸린다 "마다 실행됩니다 . 0.01 초가 될 수 있습니다. 19 시간이 될 수 있습니다.
cron보다 빠르게 스케줄러를 작성했습니다. 나는 또한 중복 가드를 구현했습니다. 이전 프로세스가 아직 실행중인 경우 새 프로세스를 시작하지 않도록 스케줄러를 구성 할 수 있습니다. https://github.com/sioux1977/scheduler/wiki 에서 살펴보세요
nanosleep (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
이전 답변 이후로 나는 다르고 아마도 더 나은 또 다른 솔루션을 생각해 냈습니다. 이 코드를 사용하면 마이크로 초 정밀도로 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
중복 실행을 방지하려면 해당 스레드에 설명 된 잠금 메커니즘을 사용하십시오 .