Подтвердить что ты не робот

Цикл времени в оболочке

Недавно я начал изучать оболочку script, поэтому я не знаю много о ней.

Я пытаюсь найти пример цикла, основанного на времени, но не имеющего удачи.

Я хочу запустить цикл за определенное количество времени, скажем, 1 час. Таким образом, цикл работает в течение часа, а затем автоматически завершается.

Изменить: этот цикл будет работать непрерывно без сна, поэтому условие цикла должно основываться на времени начала цикла и текущем времени, а не во сне.

4b9b3361

Ответ 1

Лучший способ сделать это - использовать переменную $SECONDS, которая имеет счет времени, в течение которого работает script (или shell). В приведенном ниже примере показано, как запустить цикл while в течение 3 секунд.

#! /bin/bash
end=$((SECONDS+3))

while [ $SECONDS -lt $end ]; do
    # Do what you want.
    :
done

Ответ 2

Caveat. Все решения в этом ответе - кроме ksh one - могут вернуться до (но не включая) 1 секунду раньше, так как они основаны на счетчике целых секунд, что авансы, основанные на часах реального времени (системы), а не на основе того, когда началось выполнение кода.


bash, ksh, zsh, используя специальную переменную оболочки $SECONDS:

Немного упрощенная версия ответа @bsravanin.

Вкратце говоря, $SECONDS содержит количество секунд, прошедших до сих пор в script.

В bash и zsh вы получаете целые секунды, продвигающиеся по импульсу системных (в реальном времени) часов, т.е. подсчет за кулисами действительно не начинается с 0 (!), но при любом с момента последнего полного второго дня после запуска script или переменной SECONDS было reset.

В отличие от этого, ksh работает так, как и следовало ожидать: подсчет действительно начинается с 0, когда вы reset $SECONDS; кроме того, $SECONDS сообщает дробные секунды в ksh.

Следовательно, единственная оболочка, в которой это решение работает разумно предсказуемо и точно, ksh. Тем не менее для грубых измерений и таймаутов он может по-прежнему использоваться в bash и zsh.

Примечание. Следующая строка использует строку bash shebang; просто подставляя ksh или zsh для bash, запустим script с этими оболочками.

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

Решение для оболочек только для POSIX-функций, таких как sh (dash) на Ubuntu ($SECONDS не совместимо с POSIX)

Убрана версия ответа @dcpomero.

Используется время epoch, возвращаемое date +%s (секунды, прошедшие с 1 января 1970 года) и синтаксис 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

Ответ 3

Вы можете попробовать это

starttime = `date +%s`
while [ $(( $(date +%s) - 3600 )) -lt $starttime ]; do
done

где 'date +%s' задает текущее время в секундах.

Ответ 4

date +%s даст вам секунды с эпохи, поэтому что-то вроде

startTime = `date +%s`
timeSpan = #some number of seconds
endTime = timeSpan + startTime

while (( `date +%s` < endTime )) ; do
    #code
done

Возможно, вам понадобятся некоторые изменения, так как мой bash ржавый

Ответ 5

Вы можете изучить параметр -d date.

Ниже приведен фрагмент оболочки script для иллюстрации. Это похоже на другие ответы, но может быть более полезным в разных сценариях.

# 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

Затем вы можете вызвать script разными способами, которые понимает дата:

$ ./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