У меня есть скрипт оболочки, который регулярно выполняется через cron/crontab. Я ввожу туда sleep
команду на несколько минут:
sleep 5m # Waits 5 minutes.
Мне приходится это делать, поскольку последующие действия зависят от согласованного состояния файлов, которые необходимо синхронизировать с другими (независимыми) процессами.
Если мой компьютер выходит из спящего/приостановленного режима, я не хочу продолжать выполнение скрипта (так как компьютер может просто проснуться через 4 минуты и 59 секунд, и файлы еще не будут синхронизированы).
Как можно проверить в скрипте оболочки, что пробуждение из режима ожидания произошло более 5 минут назад?
(похоже, дата /var/log/pm-suspend.log
не обновлена в моей системе)
решение1
Прежде всего, отметим, что sleep
это не учитывает время отстранения.
Например, если вы выполните команду sleep 5m
, затем приостановите работу компьютера, а затем через 4 минуты разбудите его, то sleep
команда завершится через 9 минут после запуска. Он будет спать 5 минут без приостановки.
Учитывая это, я не думаю, что вам вообще нужен тот хак, который вы ищете. Ваш вопрос подразумевал противоположное, неверное предположение, а именно, что sleep 5m
команда может спать в течение 4 минут и 59 секунд, которые компьютер провел в состоянии ожидания, и 1 секунды бодрствования.
Учитывая все вышесказанное, давайте рассмотрим один из возможных способов узнать, был ли компьютер приостановлен между двумя моментами.
Есть несколько системных часов, описанных в clock_gettime(2)
руководстве.
Один из них — это CLOCK_MONOTONIC
, это не учитывает время ожидания. Это значение в секундах, от некоторой произвольной начальной точки, выражающее количество времени, которое компьютер провел фактически бодрствующим.
Есть еще один, CLOCK_REALTIME
который выражает реальное время мира. Однако он склонен к резким скачкам, если часы скорректированы, поэтому не является полностью надежным. Вместо этого давайте использовать CLOCK_BOOTTIME
. Это значение в секундах, от некоторой произвольной начальной точки (предположительно, времени загрузки системы), включая время, проведенное компьютером в состоянии ожидания.
Вы можете распечатать эти два значения с помощью таких команд, как
python3 -c 'import time; print(time.clock_gettime(time.CLOCK_MONOTONIC))'
python3 -c 'import time; print(time.clock_gettime(time.CLOCK_BOOTTIME))'
(Существует также более простой синтаксис для получения монотонного времени; я намеренно выбрал синтаксис, который работает для обоих видов часов.)
В определенный момент запросите эти два значения и вычислите их разницу. В определенный другой момент сделайте это снова.
Разница между этими двумя разностями дает вам количество времени, в течение которого компьютер был приостановлен между ними. С небольшой погрешностью измерения, так как два значения не могут быть запрошены в один и тот же момент.
решение2
В одну сторону
Время последнего резюме должно быть доступно в systemd
системе журналов, например:
journalctl -r | awk '/resume/ {print $0; exit}'
Таким образом, вы можете присвоить временную метку в short-iso
формате переменной, например:
lr="$(journalctl -r -o short-iso | awk '/resume/ {printf "%s", $1; exit}')"
и добавьте к нему пять минут, одновременно преобразуя его в метку времени Unix, например:
lr5="$(date -d "$lr + 5 minutes" +'%s')"
и сравнить/оценить более позднюю и текущую временную метку Unix с помощью чего-то вроде (bash
определенный синтаксис):
if [[ "$(date +'%s')" -ge "$lr5" ]]
then
echo "Five minutes have passed since last resume."
# Your command/s here
fi
Другой путь
Вы можете создать свою собственную временную метку, поместив файл скрипта в /lib/systemd/system-sleep/
каталог, используя этот шаблон:
#!/bin/sh
case "${1}" in
pre)
# Command(s)/script(s) to execute before system goes to sleep/hibernate
# nothing
;;
post)
# Command(s)/script(s) to execute after system wakes up from sleep/hibernate
# Save your timestamp e.g.:
# /bin/date +'%s' > /home/user/timestamp.log
;;
esac
И используйте логику, похожую на первый способ, для анализа и оценки на основе временной метки из вашего собственного файла журнала.
Уведомление: Для использования второго способа запуска скриптов, которым требуется/зависит от сетевого подключения, см. первый раздел:Часть скрипта, связанная с сетью, не будет запущена в /lib/systemd/system-sleep.