如何使unix脚本每15秒运行一次?
我已经看到了一些解决方案,包括观看和在后台运行循环(和休眠)脚本,但没有什么是理想的 我有一个脚本,需要每15秒运行一次,因为cron不支持秒,所以我只能考虑其他问题如何使unix脚本每15秒运行一次?,unix,cron,command,sleep,Unix,Cron,Command,Sleep,我已经看到了一些解决方案,包括观看和在后台运行循环(和休眠)脚本,但没有什么是理想的 我有一个脚本,需要每15秒运行一次,因为cron不支持秒,所以我只能考虑其他问题 在unix上每15秒运行一次脚本的最健壮、最有效的方法是什么?脚本还需要在重新启动后运行。我会使用cron每分钟运行一个脚本,并使该脚本在运行之间睡眠15秒,运行脚本四次 (这假设脚本运行速度很快——如果不是,您可以调整睡眠时间。) 这样,您就可以享受到cron的所有好处以及15秒的运行时间 编辑:另请参见@bmb下面的评论。在后
在unix上每15秒运行一次脚本的最健壮、最有效的方法是什么?脚本还需要在重新启动后运行。我会使用cron每分钟运行一个脚本,并使该脚本在运行之间睡眠15秒,运行脚本四次 (这假设脚本运行速度很快——如果不是,您可以调整睡眠时间。) 这样,您就可以享受到
cron
的所有好处以及15秒的运行时间
编辑:另请参见@bmb下面的评论。在后台运行该操作不会吗
#!/bin/sh
while [ 1 ]; do
echo "Hell yeah!" &
sleep 15
done
这是最有效的。重要部分仅每15秒执行一次,脚本在其余时间处于休眠状态(因此不会浪费周期)。如果您坚持从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/u脚本。它使用结构timespec
,用于指定纳秒精度的时间间隔
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
为避免可能的执行重叠,请使用中所述的锁定机制。上述修改版本:
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
自从我上一次回答之后,我提出了另一个不同的解决方案,也许更好。此代码允许进程以微秒的精度每分钟运行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
我编写了一个比cron更快的调度器。我还实施了重叠保护。如果前一个进程仍在运行,则可以将计划程序配置为不启动新进程。看看跑步需要多长时间?@Aiden:哈!我的复仇女神,我们又见面了!如果脚本的运行时间不一致,请复制四份脚本。一个人在开始前睡15秒,另一个睡30秒,另一个睡45秒,另一个睡0秒。然后每分钟跑四次。@RichieHindle-别害怕,我因为没有把分钟变成秒而被暗杀。但是我在观察你:这个cron每1分钟触发一次,外部脚本应该运行内部脚本三次,而不是四次。否则,最后一分钟的最后一次跑步将与下一分钟的第一次跑步重叠。这将是每分钟运行内部脚本5次,而不是4次。这对我来说非常有效。上面关于使用后台任务的解决方案产生了几个子进程,并导致我端内存问题。如果运行php脚本,请执行以下操作:
***sleep 15;php/foo/bar/your_script
如果运行php脚本,可以在前面加上一行/usr/bin/php
添加到您的php脚本顶部,并使其可执行我感到很尴尬,因为我不得不用谷歌搜索这个解决方案。也许stackoverflow让我思考得更少。作为对@Hacknightly的回应,只有当脚本超过15秒的运行时间和/或任务无法释放足够的内存供系统使用时才会发生这种情况。我继续说,我猜它们不需要纳秒精度,因为它们每15秒生成一个shell脚本,不是内核线程。@ParthianShot可能是,但你永远不知道。编辑必须至少有8个字符(这是愚蠢的,IMHO),因此我无法在第3行末尾添加&
。在任何情况下,这并不是每15秒运行一次。此操作每“15秒运行一次,无论运行多长时间echo hello
。可能是0.01秒;可能是19个小时。-1 OP没有说他需要避免重复执行;这东西可能是可重入的。另外,这并没有回答问题。请编辑原始的,而不是再次发布!
#! /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