Sleep until a specific time/date

I want my bash script to sleep until a specific time. So, I want a command like "sleep" which takes no interval but an end time and sleeps until then.

The "at"-daemon is not a solution, as I need to block a running script until a certain date/time.

Is there such a command?

115105 次浏览

You can calculate the number of seconds between now and the wake-up time and use the existing 'sleep' command.

使用 sleep,但使用 date计算时间。您需要使用 date -d进行此操作。例如,假设你想等到下周:

expr `date -d "next week" +%s` - `date -d "now" +%s`

只要用你想等待的日期替换“下周”,然后将这个表达式赋值,然后睡上几秒钟:

startTime=$(date +%s)
endTime=$(date -d "next week" +%s)
timeToWait=$(($endTime- $startTime))
sleep $timeToWait

好了!

正如亡命之徒程序员所提到的,我认为解决方案只是睡眠正确的秒数。

要在 bash 中执行此操作,请执行以下操作:

current_epoch=$(date +%s)
target_epoch=$(date -d '01/01/2010 12:00' +%s)


sleep_seconds=$(( $target_epoch - $current_epoch ))


sleep $sleep_seconds

为了将精度降低到纳秒(有效地更多地是在毫秒左右) ,可以使用下面的语法:

current_epoch=$(date +%s.%N)
target_epoch=$(date -d "20:25:00.12345" +%s.%N)


sleep_seconds=$(echo "$target_epoch - $current_epoch"|bc)


sleep $sleep_seconds

注意,macOS/OS X 不支持低于秒的精度,您需要使用 brew中的 coreutils代替 看看这些说明

您也许可以使用“ at”向您的脚本发送一个信号,脚本等待这个信号。

您可以通过向进程发送 SIGSTOP 信号来停止它的执行,然后通过向它发送 SIGCONT 信号来使它恢复执行。

所以你可以通过发送一个 SIGSTOP 来停止你的脚本:

kill -SIGSTOP <pid>

然后使用 at 守护进程以相同的方式发送 SIGCONT 来唤醒它。

大概,你的脚本会告诉你它什么时候想要被唤醒,什么时候想要睡觉。

接下来是 SpoonMeiser 的回答,下面是一个具体的例子:

$cat ./reviveself


#!/bin/bash


# save my process ID
rspid=$$


# schedule my own resuscitation
# /bin/sh seems to dislike the SIGCONT form, so I use CONT
# at can accept specific dates and times as well as relative ones
# you can even do something like "at thursday" which would occur on a
# multiple of 24 hours rather than the beginning of the day
echo "kill -CONT $rspid"|at now + 2 minutes


# knock myself unconscious
# bash is happy with symbolic signals
kill -SIGSTOP $rspid


# do something to prove I'm alive
date>>reviveself.out
$

TimeTowait = $(($end-$start))

注意,“ timeTowait”可能是一个负数!(例如,如果您指定睡眠到“15:57”,现在是“15:58”)。因此,你必须检查它,以避免奇怪的信息错误:

#!/bin/bash
set -o nounset


### // Sleep until some date/time.
# // Example: sleepuntil 15:57; kdialog --msgbox "Backup needs to be done."




error() {
echo "$@" >&2
exit 1;
}


NAME_PROGRAM=$(basename "$0")


if [[ $# != 1 ]]; then
error "ERROR: program \"$NAME_PROGRAM\" needs 1 parameter and it has received: $#."
fi




current=$(date +%s.%N)
target=$(date -d "$1" +%s.%N)


seconds=$(echo "scale=9; $target - $current" | bc)


signchar=${seconds:0:1}
if [ "$signchar" = "-" ]; then
error "You need to specify in a different way the moment in which this program has to finish, probably indicating the day and the hour like in this example: $NAME_PROGRAM \"2009/12/30 10:57\"."
fi


sleep "$seconds"


# // End of file

I wanted an script that only checked the hours and minutes so I could run the script with the same parameters every day. I don't want to worry about which day will be tomorrow. So I used a different approach.

target="$1.$2"
cur=$(date '+%H.%M')
while test $target != $cur; do
sleep 59
cur=$(date '+%H.%M')
done

脚本的参数是小时和分钟,所以我可以这样写:

til 7 45 && mplayer song.ogg

(til 是脚本的名称)

再也不会因为你打错了日期而迟到了,干杯!

下面是我刚才为同步多个测试客户机而编写的内容:

#!/usr/bin/python
import time
import sys


now = time.time()
mod = float(sys.argv[1])
until = now - now % mod + mod
print "sleeping until", until


while True:
delta = until - time.time()
if delta <= 0:
print "done sleeping ", time.time()
break
time.sleep(delta / 2)

这个脚本睡眠到下一个“圆形”或“尖锐”的时间。

A simple use case is to run ./sleep.py 10; ./test_client1.py in one terminal and ./sleep.py 10; ./test_client2.py in another.

编辑样本: 2020年4月22日星期三,10:30到10点之间: 55 < br/> (阅读样本的重要性)

一般方法(避免无用的叉子!)

As this question was asked 4 years ago, this first part concerns old bash versions:

(注意: 这个方法使用 date -f,它不是 POSIX,不能在 MacOS 下工作! 如果是在 Mac 下,转到我的 纯粹的(a href = “/questions/tags/bash”class = “ post-tag”title = “ show questions tag & # 39; bash & # 39;”aria-label = “ show questions tag & # 39; bash & # 39;”rel = “ tag”aria-labelledby = “ bash-Container”> bash 函数)

为了减少 forks,与其两次运行 date,我更喜欢使用以下方法:

简单的初始样本

sleep $(( $(date -f - +%s- <<< "tomorrow 21:30"$'\nnow') 0 ))

where tomorrow 21:30 could be replaced by any kind of date and format recognized by date, in the future .

if read -rp "Sleep until: "  targetTime ;then
sleep $(( $(date -f - +%s- <<< "$targetTime"$'\nnow') 0 ))
fi

高精度(纳秒级)

几乎一样:

sleep $(bc <<<s$(date -f - +'t=%s.%N;' <<<$'07:00 tomorrow\nnow')'st-t')

到达 下次吧

对于到达 下集 HH:MM意味着今天如果可能,明天如果太晚:

sleep $((($(date -f - +%s- <<<$'21:30 tomorrow\nnow')0)%86400))

This works under , and other modern shells, but you have to use:

sleep $(( ( $(printf 'tomorrow 21:30\nnow\n' | date -f - +%s-)0 )%86400 ))

under lighter shells like or .

纯净的 路,没有岔路! !

在 MacOS 下测试!

我编写了 两个小函数: sleepUntilsleepUntilHires

 Syntax:
sleepUntil [-q] <HH[:MM[:SS]]> [more days]
-q Quiet: don't print sleep computed argument
HH          Hours (minimal required argument)
MM          Minutes (00 if not set)
SS          Seconds (00 if not set)
more days   multiplied by 86400 (0 by default)

As new versions of bash do offer a printf option to retrieve date, for this new way to 睡到 HH: MM whithout using date or any other fork, I've build a little function. Here it is:

sleepUntil() { # args: [-q] <HH[:MM[:SS]]> [more days]
local slp tzoff now quiet=false
[ "$1" = "-q" ] && shift && quiet=true
local -a hms=(${1//:/ })
printf -v now '%(%s)T' -1
printf -v tzoff '%(%z)T' $now
tzoff=$((0${tzoff:0:1}(3600*10#${tzoff:1:2}+60*10#${tzoff: -2})))
slp=$(((( 86400 + ( now - now%86400 ) +
10#$hms*3600+10#${hms[1]:-0}*60+10#${hms[2]:-0} -
tzoff - now
) % 86400 ) + 10#${2:-0} * 86400
))
$quiet || printf 'sleep %ss, -> %(%c)T\n' $slp $((now+slp))
read -t $slp _
}

然后:

sleepUntil 10:37 ; date +"Now, it is: %T"
sleep 49s, -> Wed Apr 22 10:37:00 2020
Now, it is: 10:37:00


sleepUntil -q 10:37:44 ; date +"Now, it is: %T"
Now, it is: 10:37:44


sleepUntil 10:50 1 ; date +"Now, it is: %T"
sleep 86675s, -> Thu Apr 23 10:50:00 2020
^C

如果目标是 之前,这将睡到明天:

sleepUntil 10:30 ; date +"Now, it is: %T"
sleep 85417s, -> Thu Apr 23 10:30:00 2020
^C


sleepUntil 10:30 1 ; date +"Now, it is: %T"
sleep 171825s, -> Fri Apr 24 10:30:00 2020
^C

使用 GNU/Linux 下的 进行 HiRes 时间

最近的 ,从版本5.0添加新的 $EPOCHREALTIME变量与微秒。从这里有一个 sleepUntilHires函数。

sleepUntilHires() { # args: [-q] <HH[:MM[:SS[.xxx]]]> [more days]
local slp tzoff now quiet=false musec musleep tmu
[ "$1" = "-q" ] && shift && quiet=true
local -a hms
IFS=: read -a hms <<<${1}
printf -v tmu %.06f ${hms[2]:-0}
printf -v hms[2] %.0f ${tmu%.*}
tmu=${tmu#*.}
printf -v now '%(%s)T' -1
IFS=. read now musec <<<$EPOCHREALTIME
musleep=$((2000000+10#$tmu-10#$musec))
printf -v tzoff '%(%z)T\n' $now
tzoff=$((0${tzoff:0:1}(3600*10#${tzoff:1:2}+60*10#${tzoff:3:2})))
slp=$(((( 86400 + ( now - now%86400 ) +
10#$hms*3600+10#0${hms[1]:-0}*60+10#${hms[2]:-0} -
tzoff - now - 1
) % 86400 ) + 10#${2:-0} * 86400
)).${musleep:1}
$quiet ||
printf 'sleep %ss, -> %(%c)T.%s\n' $slp $((now+${slp%.*}+1)) $tmu
read -t $slp _
}

请注意: 这种使用 read -t的方式是内置的,而不是 sleep。不幸的是,当在后台运行时,如果没有真正的 TTY,这将无法工作。如果你想用 sleep代替 read -t,请随意 计划在后台脚本中运行它... (但是对于后台进程,可以考虑使用 cron和/或 at代替所有这些)

Skip next paragraph for tests and warning about $ËPOCHSECONDS!

旧的方法使用 /proc/timer_list,避免对正常用户,由最近的内核! !

在 Linux 内核下,您将找到一个名为 /proc/timer_list的变量文件,在这个文件中,您可以读取 纳秒中的 offsetnow变量。因此,我们可以计算睡眠时间,以达到 非常好期望的时间。

(我编写这个程序是为了在非常大的日志文件中生成和跟踪特定的事件,这些日志文件包含一秒钟的千行内容)。
mapfile  </proc/timer_list _timer_list
for ((_i=0;_i<${#_timer_list[@]};_i++));do
[[ ${_timer_list[_i]} =~ ^now ]] && TIMER_LIST_SKIP=$_i
[[ ${_timer_list[_i]} =~ offset:.*[1-9] ]] && \
TIMER_LIST_OFFSET=${_timer_list[_i]//[a-z.: ]} && \
break
done
unset _i _timer_list
readonly TIMER_LIST_OFFSET TIMER_LIST_SKIP


sleepUntilHires() {
local slp tzoff now quiet=false nsnow nsslp
[ "$1" = "-q" ] && shift && quiet=true
local hms=(${1//:/ })
mapfile -n 1 -s $TIMER_LIST_SKIP nsnow </proc/timer_list
printf -v now '%(%s)T' -1
printf -v tzoff '%(%z)T\n' $now
nsnow=$((${nsnow//[a-z ]}+TIMER_LIST_OFFSET))
nsslp=$((2000000000-10#${nsnow:${#nsnow}-9}))
tzoff=$((0${tzoff:0:1}(3600*${tzoff:1:2}+60*${tzoff:3:2})))
slp=$(( ( 86400 + ( now - now%86400 ) +
10#$hms*3600+10#${hms[1]}*60+${hms[2]} -
tzoff - now - 1
) % 86400)).${nsslp:1}
$quiet || printf 'sleep %ss, -> %(%c)T\n' $slp $((now+${slp%.*}+1))
sleep $slp
}

在定义了两个 只读变量 TIMER_LIST_OFFSETTIMER_LIST_SKIP之后,该函数将非常快速地访问用于计算睡眠时间的变量文件 /proc/timer_list:

小小的测试功能

tstSleepUntilHires () {
local now next last
printf -v next "%(%H:%M:%S)T" $((${EPOCHREALTIME%.*}+1))
sleepUntilHires $next
date -f - +%F-%T.%N < <(echo now;sleep .92;echo now)
printf -v next "%(%H:%M:%S)T" $((${EPOCHREALTIME%.*}+1))
sleepUntilHires $next
date +%F-%T.%N
}

可能会显示如下内容:

sleep 0.244040s, -> Wed Apr 22 10:34:39 2020
2020-04-22-10:34:39.001685312
2020-04-22-10:34:39.922291769
sleep 0.077012s, -> Wed Apr 22 10:34:40 2020
2020-04-22-10:34:40.004264869
  • 下一秒开始,
  • 那就打印时间
  • 那就等0.92秒
  • 那就打印时间
  • 计算0.07秒到下一秒
  • 那就睡0.07秒
  • 打印时间。

注意不要混合 $EPOCHSECOND$EPOCHREALTIME

读我的 关于 ABC0和 $EPOCHREALTIME之间差异的警告

这个函数使用 $EPOCHREALTIME,所以不要使用 $EPOCHSECOND来建立 下一秒:

示例问题: 试图打印时间下一步四舍五入2秒:

for i in 1 2;do
printf -v nextEvenSecond "%(%T)T" $(((EPOCHSECONDS/2)*2+2))
echo $nextEvenSecond
sleepUntilHires $nextEvenSecond
IFS=. read now musec <<<$EPOCHREALTIME
printf "%(%c)T.%s\n" $now $musec
done

可能产生:

11:44:32
sleep 1.485212s, -> Wed Nov  9 11:44:32 2022.000000
Wed Nov  9 11:44:32 2022.000311
11:44:32
sleep 86399.999143s, -> Thu Nov 10 11:44:32 2022.000000

你要等一天而不是两秒钟! ! !

你必须使用 $EPOCHREALTIME:

    printf -v nextEvenSecond "%(%T)T" $(((${EPOCHREALTIME%.*}/2)*2+2))
11:48:12
sleep 0.300672s, -> Wed Nov  9 11:48:12 2022.000000
Wed Nov  9 11:48:12 2022.000345
11:48:14
sleep 1.998397s, -> Wed Nov  9 11:48:14 2022.000000
Wed Nov  9 11:48:14 2022.000536
11:48:16
sleep 1.998916s, -> Wed Nov  9 11:48:16 2022.000000
Wed Nov  9 11:48:16 2022.000325

关于 sleep及/或 read -t

在这个函数中,我使用 read -t(暂停)而不是 sleep,原因有二:

  • 这允许用户通过按 Return键来中断 睡觉。< br/> (变体: IFS= read -sn 1 -t $slp _,允许用户按 Any键进行中断)。
  • sleep意味着对 /bin/sleep的调用(叉子) ,因为它不是 但是

For avoiding user interrupt by keyboard interaction aka for running this 非互动的, you could

  • 创建一个伪 tty(文件描述符) ,用于在 sleepUntil.source脚本开头重定向 read的输入:

    exec {_dummySleepFd}<> <(:)
    

    然后替换

    read -t $slp _
    

    by

    read -u $_dummySleepFd -t $slp _
    
  • 如果 bash 实现允许这样做,则加载 sleep 可装载的内建物(参见 sudo apt install bash-builtins) :

    enable -f sleep sleep
    

    如果你的 $BASH_LOADABLES_PATH已设定,否则:

    enable -f /usr/lib/bash/sleep sleep
    

    卸载/关闭:

    enable -d sleep
    

一些测试(在我的覆盆子上) :

exec {_dummySleepFd}<> <(:)
s=${EPOCHREALTIME/.};read -u $_dummySleepFd -t .01;echo $((${EPOCHREALTIME/.}-s))
10975


s=${EPOCHREALTIME/.};read -u $_dummySleepFd -t .01;echo $((${EPOCHREALTIME/.}-s))
10977

/bin/sleep:

s=${EPOCHREALTIME/.};sleep .01;echo $((${EPOCHREALTIME/.}-s))
60676


s=${EPOCHREALTIME/.};sleep .01;echo $((${EPOCHREALTIME/.}-s))
47910


s=${EPOCHREALTIME/.};sleep .01;echo $((${EPOCHREALTIME/.}-s))
44585

第一次,/bin/sleep是来自文件系统的 上膛了。这个更长。但无论如何,即使在 缓存中,将 叉子运行到 sleep也是资源杀手..。

enable -f /usr/lib/bash/sleep sleep
s=${EPOCHREALTIME/.};sleep .01;echo $((${EPOCHREALTIME/.}-s))
10803


s=${EPOCHREALTIME/.};sleep .01;echo $((${EPOCHREALTIME/.}-s))
10760

似乎比使用 read -u $_dummySleepFd -t ...好一点

Here is a simple Bash one-liner:

sleep $(expr $(date -d "03/21/2014 12:30" +%s) - $(date +%s))

这里有一个解决方案,它完成这项工作,并通知用户还剩下多少时间。 I use it almost everyday to run scripts during the night (using cygwin, as I couldn't get cron to work on windows)

特征

  • 精确到秒
  • 检测系统时间变化并进行适应
  • 告知剩余时间的智能输出
  • 24小时输入格式
  • 返回 true 以便能够与 &&连接

样本运行

$ til 13:00 && date
1 hour and 18 minutes and 26 seconds left...
1 hour and 18 minutes left...
1 hour and 17 minutes left...
1 hour and 16 minutes left...
1 hour and 15 minutes left...
1 hour and 14 minutes left...
1 hour and 10 minutes left...
1 hour and  5 minutes left...
1 hour and  0 minutes left...
55 minutes left...
50 minutes left...
45 minutes left...
40 minutes left...
35 minutes left...
30 minutes left...
25 minutes left...
20 minutes left...
15 minutes left...
10 minutes left...
5 minutes left...
4 minutes left...
3 minutes left...
2 minutes left...
1 minute left...
Mon, May 18, 2015  1:00:00 PM

(末尾的日期不是函数的一部分,而是由于 && date)

密码

til(){
local hour mins target now left initial sleft correction m sec h hm hs ms ss showSeconds toSleep
showSeconds=true
[[ $1 =~ ([0-9][0-9]):([0-9][0-9]) ]] || { echo >&2 "USAGE: til HH:MM"; return 1; }
hour=${BASH_REMATCH[1]} mins=${BASH_REMATCH[2]}
target=$(date +%s -d "$hour:$mins") || return 1
now=$(date +%s)
(( target > now )) || target=$(date +%s -d "tomorrow $hour:$mins")
left=$((target - now))
initial=$left
while (( left > 0 )); do
if (( initial - left < 300 )) || (( left < 300 )) || [[ ${left: -2} == 00 ]]; then
# We enter this condition:
# - once every 5 minutes
# - every minute for 5 minutes after the start
# - every minute for 5 minutes before the end
# Here, we will print how much time is left, and re-synchronize the clock


hs= ms= ss=
m=$((left/60)) sec=$((left%60)) # minutes and seconds left
h=$((m/60)) hm=$((m%60)) # hours and minutes left


# Re-synchronise
now=$(date +%s) sleft=$((target - now)) # recalculate time left, multiple 60s sleeps and date calls have some overhead.
correction=$((sleft-left))
if (( ${correction#-} > 59 )); then
echo "System time change detected..."
(( sleft <= 0 )) && return # terminating as the desired time passed already
til "$1" && return # resuming the timer anew with the new time
fi


# plural calculations
(( sec > 1 )) && ss=s
(( hm != 1 )) && ms=s
(( h > 1 )) && hs=s


(( h > 0 )) && printf %s "$h hour$hs and "
(( h > 0 || hm > 0 )) && printf '%2d %s' "$hm" "minute$ms"
if [[ $showSeconds ]]; then
showSeconds=
(( h > 0 || hm > 0 )) && (( sec > 0 )) && printf %s " and "
(( sec > 0 )) && printf %s "$sec second$ss"
echo " left..."
(( sec > 0 )) && sleep "$sec" && left=$((left-sec)) && continue
else
echo " left..."
fi
fi
left=$((left-60))
sleep "$((60+correction))"
correction=0
done
}

OpenBSD上,可以使用以下方法将 */55分钟的 crontab(5)任务压缩成每小时一次的 00任务(以确保生成更少的电子邮件,同时在确切的间隔执行相同的任务) :

#!/bin/sh -x
for k in $(jot 12 00 55)
do
echo $(date) doing stuff
sleep $(expr $(date -j +%s $(printf %02d $(expr $k + 5))) - $(date -j +%s))
done

Note that the date(1) would also break the sleep(1) by design on the final iteration, as 60 minutes is not a valid time (unless it is!), thus we won't have to wait any extra time prior to getting our email report.

还要注意的是,如果其中一个迭代需要超过5分钟的时间,那么 sleep也会因为根本不睡觉而失败(因为负数被解释为命令行选项,而不是绕到下一个小时甚至永恒) ,从而确保你的工作仍然可以在分配的小时内完成(例如,如果只有一个迭代需要5分钟多一点,那么我们仍然有时间赶上,没有任何东西绕到下一个小时)。

printf(1)是必需的,因为 date期望在分钟规范中正好有两个数字。

 function sleepuntil() {
local target_time="$1"
today=$(date +"%m/%d/%Y")
current_epoch=$(date +%s)
target_epoch=$(date -d "$today $target_time" +%s)
sleep_seconds=$(( $target_epoch - $current_epoch ))


sleep $sleep_seconds
}


target_time="11:59"; sleepuntil $target_time

我整合了一个名为 催眠的小实用程序来完成这项工作。在此之前,它使用 crontab 语法和块进行配置。

#!/bin/bash
while [ 1 ]; do
hypnos "0 * * * *"
echo "running some tasks..."
# ...
done

我写 https://tamentis.com/projects/sleepuntil/就是为了这个目的。大部分代码来自 BSD‘ at’,所以它是相当标准兼容的:

$ sleepuntil noon && sendmail something

使用 tarry 这是我专门写的工具。

Https://github.com/metaphyze/tarry/

这是一个简单的命令行工具,用于等待特定的时间。这与“睡眠”不同,“睡眠”会等待一段时间。如果您想在特定的时间执行某些操作,或者更有可能在同一时间执行多个操作,例如测试服务器是否可以处理多个非常同时的请求,那么这非常有用。你可以像这样在 Linux,Mac 或者 Windows 上使用“ & &”:

   tarry -until=16:03:04 && someOtherCommand

这将等到下午4:03:04,然后执行一些 OtherCommand。下面是一个 Linux/Mac 的例子,说明如何运行所有计划同时启动的多个请求:

   for request in 1 2 3 4 5 6 7 8 9 10
do
tarry -until=16:03:04 && date > results.$request &
done

Ubuntu、 Linux 和 Windows 二进制文件可以通过页面上的链接获得。

为了扩展主要答案,下面是一些关于日期字符串操作的有效例子:

sleep $(($(date -f - +%s- <<< $'+3 seconds\nnow')0)) && ls


sleep $(($(date -f - +%s- <<< $'3 seconds\nnow')0)) && ls


sleep $(($(date -f - +%s- <<< $'3 second\nnow')0)) && ls


sleep $(($(date -f - +%s- <<< $'+2 minute\nnow')0)) && ls


sleep $(($(date -f - +%s- <<< $'tomorrow\nnow')0)) && ls


sleep $(($(date -f - +%s- <<< $'tomorrow 21:30\nnow')0)) && ls


sleep $(($(date -f - +%s- <<< $'3 weeks\nnow')0)) && ls


sleep $(($(date -f - +%s- <<< $'3 week\nnow')0)) && ls


sleep $(($(date -f - +%s- <<< $'next Friday 09:00\nnow')0)) && ls


sleep $(($(date -f - +%s- <<< $'2027-01-01 00:00:01 UTC +5 hours\nnow')0)) && ls

再考虑一下这个简洁的 Bash 俏皮话:

sleep $((`date -d "22:00" +%s`-`date  +%s`))

这是一个 Bash v4.4.20(1)算术表达式,由两个日期命令替换组成。第一个 date 命令输出目标,直到以秒为单位的时间(自1970年以来) ,后者输出各自的当前时间。这两个数字在算术中用一个减号分开。因此,可以获得秒作为 sleep 命令的参数。

有一个不错的小 Rust CLI 工具 打哈欠来完成这项工作。如果您已经安装了 Rust,那么这可能是一个简单的选项(cargo install yawn)。除此之外,Github 上还有 Apple 和 Linux 的可执行文件。

这个脚本将等到 4 of July, 21:44:59

while (( $(date +"%Y%m%d%H%M%S") < 20220704214459 )); do :; done
echo "It is time!"

这里有一个最后的倒计时解决方案使用标准的 pv工具,随您的发行版。

  • 使用任何 date兼容表达式而不是 5 min
  • 可以使用 pv参数获得所需的输出。
SECS=$(( $(date -d '5 min' +%s)-$(date +%s) )) && pv -L1 -s$SECS -petlI <(seq $SECS) >/dev/null