bash 脚本:固定睡眠时间在 while 循环中累加

bash 脚本:固定睡眠时间在 while 循环中累加

我是 bash 脚本编写的新手,从一些示例脚本开始。

一是:

#!/bin/bash
SECONDS=5
i=1

while true
do
        echo "`date`: Loop $i"
        i=$(( $i+1 ))
        sleep $SECONDS
done

这导致:

Sunday 10 May  15:08:20 AEST 2020: Loop 1
Sunday 10 May  15:08:25 AEST 2020: Loop 2
Sunday 10 May  15:08:35 AEST 2020: Loop 3
Sunday 10 May  15:08:55 AEST 2020: Loop 4

...这不是我期望或希望脚本执行的操作。

为什么每次循环时秒数都会加倍

bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

答案1

因为SECONDS是bash中的内部变量。它存储 shell 已运行的时间量。

man bash

SECONDS
每次引用此参数时,都会返回自 shell 调用以来的秒数。如果将值分配给 SECONDS,则后续引用时返回的值是自分配以来的秒数加上所分配的值。

所以,你的脚本的工作原理如下:

  1. 第一次使用时,它接受值 5 作为输入,初始值为 5。
  2. 然后有一个 5 秒的睡眠,当睡眠返回时,SECONDS 的值将是初始值的 5 秒 + 睡眠的 5 秒 = 10 秒
  3. 然后睡眠 10 秒(SECONDS 的当前值)加上之前 10 秒的累计时间,即为 20。
  4. 重复睡眠 20 秒加上之前的值 20 就是 40。
  5. ETC。

答案2

此构造存在一个二阶问题:如果循环中的处理需要大量时间(例如 1.4 秒),则循环只会每 6.4 秒重复一次。

如果这很重要,您可以改为计算循环数。

#!/bin/bash

Expired=$(( SECONDS + 23 ))
Tick=5
Iter=1

while (( SECONDS < Expired )); do
    echo "$(date '+%T.%N'): Loop $Iter"
    sleep 1.4  #.. Simulate work.
    echo "$(date '+%T.%N'): Idle"
    sleep $(( Iter++ * Tick - SECONDS ))
done                    

循环时间稳定在秒的整数精度范围内。

您可以执行更复杂的算术来初始化 Expired(例如,使用两个日期命令来查找午夜之前的秒数)。

相关内容