我有一个通过 cron/crontab 定期执行的 shell 脚本。我在那里输入了一个sleep
命令,执行了几分钟:
sleep 5m # Waits 5 minutes.
我必须这样做,因为随后的操作取决于需要由其他(独立)进程同步的文件的一致状态。
如果我的计算机从睡眠/挂起模式恢复,我不想继续执行脚本(因为计算机可以在 4 分 59 秒后唤醒,所以文件尚未同步)。
我如何在 shell 脚本中检查从挂起状态唤醒的时间是否超过 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 中运行。