Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使unix脚本每15秒运行一次?_Unix_Cron_Command_Sleep - Fatal编程技术网

如何使unix脚本每15秒运行一次?

如何使unix脚本每15秒运行一次?,unix,cron,command,sleep,Unix,Cron,Command,Sleep,我已经看到了一些解决方案,包括观看和在后台运行循环(和休眠)脚本,但没有什么是理想的 我有一个脚本,需要每15秒运行一次,因为cron不支持秒,所以我只能考虑其他问题 在unix上每15秒运行一次脚本的最健壮、最有效的方法是什么?脚本还需要在重新启动后运行。我会使用cron每分钟运行一个脚本,并使该脚本在运行之间睡眠15秒,运行脚本四次 (这假设脚本运行速度很快——如果不是,您可以调整睡眠时间。) 这样,您就可以享受到cron的所有好处以及15秒的运行时间 编辑:另请参见@bmb下面的评论。在后

我已经看到了一些解决方案,包括观看和在后台运行循环(和休眠)脚本,但没有什么是理想的

我有一个脚本,需要每15秒运行一次,因为cron不支持秒,所以我只能考虑其他问题


在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