Time condition loop in shell

后端 未结 8 1592
故里飘歌
故里飘歌 2020-12-04 10:34

I have just started learning shell script recently, so I don\'t know much about it.

I am trying to find example of time based while loop but not having any luck.

8条回答
  •  感动是毒
    2020-12-04 10:53

    Caveat: All solutions in this answer - except the ksh one - can return up to (but not including) 1 second early, since they're based on an integral-seconds counter that advances based on the real-time (system) clock rather than based on when code execution started.


    bash, ksh, zsh solution, using special shell variable $SECONDS:

    Slightly simplified version of @bsravanin's answer.

    Loosely speaking, $SECONDS contains the number of seconds elapsed so far in a script.

    In bash and zsh you get integral seconds advancing by the pulse of the system (real-time) clock - i.e., counting behind the scenes does not truly start at 0(!), but at whatever fraction since the last full time-of-day second the script happened to be started at or the SECONDS variable was reset.

    By contrast, ksh operates as one would expect: counting truly starts at 0 when you reset $SECONDS; furthermore, $SECONDS reports fractional seconds in ksh.

    Therefore, the only shell in which this solution works reasonably predictably and precisely is ksh. That said, for rough measurements and timeouts it may still be usable in bash and zsh.

    Note: The following uses a bash shebang line; simply substituting ksh or zsh for bash will make the script run with these shells, too.

    #!/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
    

    Solution for POSIX-features-only shells, such as sh (dash) on Ubuntu ($SECONDS is not POSIX-compliant)

    Cleaned-up version of @dcpomero's answer.

    Uses epoch time returned by date +%s (seconds elapsed since 1 January 1970) and POSIX syntax for the conditional.

    Caveat: date +%s itself (specifically, the %s format) is not POSIX-compliant, but it'll work on (at least) Linux, FreeBSD, and 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
    

提交回复
热议问题