shell中的时间条件循环
我最近才开始学习shell脚本,所以对它了解不多 我试图找到基于时间的while循环的例子,但没有任何运气 我想运行一个特定时间的循环,比如说1小时。所以循环运行一个小时,然后自动结束shell中的时间条件循环,shell,Shell,我最近才开始学习shell脚本,所以对它了解不多 我试图找到基于时间的while循环的例子,但没有任何运气 我想运行一个特定时间的循环,比如说1小时。所以循环运行一个小时,然后自动结束 编辑:此循环将在没有任何睡眠的情况下连续运行,因此循环条件应基于循环的开始时间和当前时间,而不是睡眠时间。date+%s将为您提供自纪元以来的秒数,例如 startTime = `date +%s` timeSpan = #some number of seconds endTime = timeSpan + s
编辑:此循环将在没有任何睡眠的情况下连续运行,因此循环条件应基于循环的开始时间和当前时间,而不是睡眠时间。
date+%s
将为您提供自纪元以来的秒数,例如
startTime = `date +%s`
timeSpan = #some number of seconds
endTime = timeSpan + startTime
while (( `date +%s` < endTime )) ; do
#code
done
startTime=`date+%s`
timeSpan=#一些秒数
结束时间=时间跨度+开始时间
而(`date+%s`
您可能需要进行一些编辑,因为我的bash已经生锈了最好的方法是使用$SECONDS变量,该变量包含脚本(或shell)运行的时间计数。下面的示例显示如何运行while循环3秒钟
#! /bin/bash
end=$((SECONDS+3))
while [ $SECONDS -lt $end ]; do
# Do what you want.
:
done
注意事项:此答案中的所有解决方案(除了
ksh
one)都可以提前1秒返回(但不包括),因为它们基于整数秒计数器,该计数器根据实时(系统)时钟而不是代码执行开始的时间前进
bash
,ksh
,zsh
解决方案,使用特殊的shell变量$SECONDS
:
略为简化的@bsravanin答案
粗略地说,$SECONDS
包含脚本中到目前为止经过的秒数
在bash
和zsh
中,您可以通过系统(实时)时钟的脉冲获得积分秒-即,幕后计数并非真正从0
(!)开始,但是从一天中的最后一个完整时间开始,脚本恰好在秒开始,或者重置了SECONDS
变量
相比之下,ksh
的工作方式与人们预期的一样:当您重置$SECONDS
时,计数真正开始于0
;此外,$SECONDS
报告ksh
中的分数秒
因此,此解决方案可以合理预测和精确运行的唯一外壳是ksh
。也就是说,对于粗略的测量和超时,它仍然可以在bash
和zsh
中使用
注意:下面使用了bash
shebang行;只需将ksh
或zsh
替换为bash
也将使脚本与这些shell一起运行
#!/usr/bin/env bash
secs=3600 # Set interval (duration) in seconds.
SECONDS=0 # Reset $SECONDS; counting of seconds will (re)start from 0(-ish).
while (( SECONDS < secs )); do # Loop until interval has elapsed.
# ...
done
你可以试试这个
starttime = `date +%s`
while [ $(( $(date +%s) - 3600 )) -lt $starttime ]; do
done
其中
'date+%s'
以秒为单位给出当前时间。您可以浏览日期的-d
选项
下面是要举例说明的shell脚本片段。它与其他答案类似,但在不同的场景中可能更有用
# set -e to exit if the time provided by argument 1 is not valid for date.
# The variable stop_date will store the seconds since 1970-01-01 00:00:00
# UTC, according to the date specified by -d "$1".
set -e
stop_date=$(date -d "$1" "+%s")
set +e
echo -e "Starting at $(date)"
echo -e "Finishing at $(date -d "$1")"
# Repeat the loop while the current date is less than stop_date
while [ $(date "+%s") -lt ${stop_date} ]; do
# your commands that will run until stop_date
done
然后,您可以用date理解的多种不同方式调用脚本:
$ ./the_script.sh "1 hour 4 minutes 3 seconds"
Starting at Fri Jun 2 10:50:28 BRT 2017
Finishing at Fri Jun 2 11:54:31 BRT 2017
$ ./the_script.sh "tomorrow 8:00am"
Starting at Fri Jun 2 10:50:39 BRT 2017
Finishing at Sat Jun 3 08:00:00 BRT 2017
$ ./the_script.sh "monday 8:00am"
Starting at Fri Jun 2 10:51:25 BRT 2017
Finishing at Mon Jun 5 08:00:00 BRT 2017
您可以使用可用的循环
命令,如下所示:
$ loop './do_thing.sh' --for-duration 1h --every 5s
每五秒钟一次,持续一小时。这正是我想要的,
以下是一个基于bsravanin答案的单线解决方案:
结束=$((秒+30));of=$((结束秒));而[$SECONDS-lt$end];做回显$((结束秒))秒剩余的$of;睡眠1;完成 更现代的方法
猛击
declare-ir MAX_SECONDS=5
声明-ir超时=$SECONDS+$MAX_SECONDS
而($SECONDS<$TIMEOUT));做
#福
完成
科恩
typeset-ir MAX_SECONDS=5
排版-ir超时=$SECONDS+$MAX_SECONDS
而($SECONDS<$TIMEOUT));做
#酒吧
完成
bash和其他bourne shell变体都支持这一点,但我不确定它是否在POSIX规范中,因此您应该清楚地指定一个比更具体的hash-bang shell/bin/sh
(这个答案的确如此,但我只是指出了它)。+1表示使用$SECONDS
@RobStarling:它确实不是POSIX的一部分(请参阅我的答案,了解仅针对POSIX的解决方案);非详尽调查:$SECONDS
适用于bash
、zsh
、ksh
。在ksh
中,它甚至会报告分数秒。这很有希望,但您的代码由于许多原因而中断;看我的答案。真的很好,但这不是一个标准:/
$ loop './do_thing.sh' --for-duration 1h --every 5s
declare -ir MAX_SECONDS=5
declare -ir TIMEOUT=$SECONDS+$MAX_SECONDS
while (( $SECONDS < $TIMEOUT )); do
# foo
done
typeset -ir MAX_SECONDS=5
typeset -ir TIMEOUT=$SECONDS+$MAX_SECONDS
while (( $SECONDS < $TIMEOUT )); do
# bar
done