最近刚开始学习shell脚本,所以不太了解。
我正在尝试查找基于时间的 while 循环的示例,但没有任何运气。
我想在特定的时间内运行一个循环,比如说 1 小时。所以循环运行一个小时,然后自动结束。
编辑:此循环将在没有任何睡眠的情况下连续运行,因此循环条件应基于循环的开始时间和当前时间,而不是睡眠。
最近刚开始学习shell脚本,所以不太了解。
我正在尝试查找基于时间的 while 循环的示例,但没有任何运气。
我想在特定的时间内运行一个循环,比如说 1 小时。所以循环运行一个小时,然后自动结束。
编辑:此循环将在没有任何睡眠的情况下连续运行,因此循环条件应基于循环的开始时间和当前时间,而不是睡眠。
最好的方法是使用 $SECONDS 变量,它计算脚本(或 shell)运行的时间。下面的示例显示了如何运行 3 秒的 while 循环。
#! /bin/bash
end=$((SECONDS+3))
while [ $SECONDS -lt $end ]; do
# Do what you want.
:
done
警告:这个答案中的所有解决方案 - 除了ksh
一个 - 可以返回(但不包括)提前 1 秒,因为它们基于基于实时(系统)时钟而不是推进的整数秒计数器基于代码执行开始的时间。
bash
, ksh
,zsh
解决方案,使用特殊的 shell 变量$SECONDS
:@bsravanin 答案的略微简化版本。
粗略地说,$SECONDS
包含脚本中到目前为止经过的秒数。
并且您会通过系统(实时)时钟bash
的脉冲获得积分秒数- 即,幕后计数并不是真正从(!)开始,而是从一天中最后一个完整时间秒以来的任何分数脚本恰好开始于或变量被重置。zsh
0
SECONDS
相比之下,ksh
按预期运行:计数真正开始于0
您重置时$SECONDS
;此外,$SECONDS
报告. 中的小数秒ksh
。
因此,该解决方案可以合理且准确地在其中工作的唯一外壳是ksh
. 也就是说,对于粗略的测量和超时,它仍然可以在bash
和zsh
中使用。
注:以下使用bash
shebang线;简单地替换ksh
或zsh
forbash
将使脚本也与这些 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
sh
( )(不符合 POSIX 标准)dash
$SECONDS
@dcomero 的答案的清理版本。
使用返回的纪元时间date +%s
(自 1970 年 1 月 1 日以来经过的秒数)和条件的 POSIX 语法。
警告:date +%s
它本身(特别是%s
格式)不符合 POSIX,但它(至少)可以在 Linux、FreeBSD 和 OSX 上运行。
#!/bin/sh
secs=3600 # Set interval (duration) in seconds.
endTime=$(( $(date +%s) + secs )) # Calculate end time.
while [ $(date +%s) -lt $endTime ]; do # Loop until interval has elapsed.
# ...
done
You can try this
starttime = `date +%s`
while [ $(( $(date +%s) - 3600 )) -lt $starttime ]; do
done
where 'date +%s'
gives the current time in seconds.
date +%s
会给你自纪元以来的秒数,所以像
startTime = `date +%s`
timeSpan = #some number of seconds
endTime = timeSpan + startTime
while (( `date +%s` < endTime )) ; do
#code
done
你可能需要一些编辑,因为我的 bash 生锈了
这正是我一直在寻找的,这是基于 bsravanin 回答的单行解决方案:
结束=$((SECONDS+30)); of=$((end-SECONDS)) ; 而 [ $SECONDS -lt $end ]; 在 $of 的左边做 echo $((end-SECONDS)) 秒;睡觉 1; 完毕;
您可以-d
探索date
.
下面是一个示例的 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
对于更现代的方法...
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