获取睡眠命令在 shell 脚本中结束的剩余秒数
get the number of seconds left for the sleep command to end in a shell script
我构建了一个 shell 脚本,它会休眠指定的分钟数并在完成时显示通知。
TIME=$(zenity --scale --title="Next Session in (?) minutes")
sleep $TIME'm'
BEEP="/usr/share/sounds/freedesktop/stereo/complete.oga"
paplay $BEEP
notify-send "Next Session" "Press <Ctrl><Shift><s> to run the script again"
我在代码的开头使用基于文件的方法阻止了程序的多个实例的执行。当用户想要 运行 脚本而另一个实例正在 运行ning 时,它会显示脚本已经 运行ning 的通知。
LOCKFILE=/tmp/lock.txt
if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then
notify-send "Already Running" $SECONDS
exit
fi
trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT
echo $$ > ${LOCKFILE}
最后删除脚本末尾的临时文件
rm -f ${LOCKFILE}
现在我想在通知中添加一个文本,告诉我 shell 脚本中的睡眠命令还有多少秒结束。 (更改已经 运行ning 通知如下)
notify-send "Already Running" $SECONDS
用自己控制的while循环实现sleep命令会影响计算机的整体性能。我认为 sleep 命令是一个更好的选择,因为它通过将自身发送到进程队列中的等待状态来优化进程。
有什么办法可以解决这个问题吗?
将脚本应该结束的时间存储在锁定文件中。
if [ -e "$LOCKFILE" ]; then
read pid endtime < "$LOCKFILE"
if kill -0 "$pid"; then
notify-send "Already running" $(($(date +%s) - $endtime))
exit
fi
fi
trap "rm -f ${LOCKFILE}" EXIT # Use cascaded trap
trap 'exit 127' INT TERM
echo $$ $(($(date +%s) + (60 * $TIME))) >"$LOCKFILE"
这里存在竞争条件;如果两个脚本几乎同时启动,当第二个启动时,第一个脚本可能在 if
内但在 echo
之前。如果您确实需要防止这种情况发生,请使用锁定目录而不是文件——目录创建是原子的,成功或失败仅在一个时间点发生(但随后您需要清除目录存在但不属于文件的神秘场景——可能是在粗心的 OOM 杀手或其他东西之后)。
我认为 Triplee 有一个很好的答案,另一种可以应用于任何可能阻塞的 运行 进程的处理方法是 bg
进程短暂地获取并保存分配的 pid $!
到文件然后 fg
过程返回。
从那里你可以计算并通过 ps
获得秒数:
TIME=$(zenity --scale --title="Next Session in (?) minutes")
SLEEP_PID_FILE="/tmp/__session_ui_sleep_pid__"
sleep $TIME'm' &
echo $! >> "${SLEEP_PID_FILE}"
fg
BEEP="/usr/share/sounds/freedesktop/stereo/complete.oga"
paplay $BEEP
notify-send "Next Session" "Press <Ctrl><Shift><s> to run the script again"
然后你可以用类似的东西找到当前经过的时间:
notify-send "Already running for $(($(date +%s)-$(date -d"$(ps -o lstart= -p$(< "${SLEEP_PID_FILE}"))" +%s))) seconds..."
我构建了一个 shell 脚本,它会休眠指定的分钟数并在完成时显示通知。
TIME=$(zenity --scale --title="Next Session in (?) minutes")
sleep $TIME'm'
BEEP="/usr/share/sounds/freedesktop/stereo/complete.oga"
paplay $BEEP
notify-send "Next Session" "Press <Ctrl><Shift><s> to run the script again"
我在代码的开头使用基于文件的方法阻止了程序的多个实例的执行。当用户想要 运行 脚本而另一个实例正在 运行ning 时,它会显示脚本已经 运行ning 的通知。
LOCKFILE=/tmp/lock.txt
if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then
notify-send "Already Running" $SECONDS
exit
fi
trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT
echo $$ > ${LOCKFILE}
最后删除脚本末尾的临时文件
rm -f ${LOCKFILE}
现在我想在通知中添加一个文本,告诉我 shell 脚本中的睡眠命令还有多少秒结束。 (更改已经 运行ning 通知如下)
notify-send "Already Running" $SECONDS
用自己控制的while循环实现sleep命令会影响计算机的整体性能。我认为 sleep 命令是一个更好的选择,因为它通过将自身发送到进程队列中的等待状态来优化进程。 有什么办法可以解决这个问题吗?
将脚本应该结束的时间存储在锁定文件中。
if [ -e "$LOCKFILE" ]; then
read pid endtime < "$LOCKFILE"
if kill -0 "$pid"; then
notify-send "Already running" $(($(date +%s) - $endtime))
exit
fi
fi
trap "rm -f ${LOCKFILE}" EXIT # Use cascaded trap
trap 'exit 127' INT TERM
echo $$ $(($(date +%s) + (60 * $TIME))) >"$LOCKFILE"
这里存在竞争条件;如果两个脚本几乎同时启动,当第二个启动时,第一个脚本可能在 if
内但在 echo
之前。如果您确实需要防止这种情况发生,请使用锁定目录而不是文件——目录创建是原子的,成功或失败仅在一个时间点发生(但随后您需要清除目录存在但不属于文件的神秘场景——可能是在粗心的 OOM 杀手或其他东西之后)。
我认为 Triplee 有一个很好的答案,另一种可以应用于任何可能阻塞的 运行 进程的处理方法是 bg
进程短暂地获取并保存分配的 pid $!
到文件然后 fg
过程返回。
从那里你可以计算并通过 ps
获得秒数:
TIME=$(zenity --scale --title="Next Session in (?) minutes")
SLEEP_PID_FILE="/tmp/__session_ui_sleep_pid__"
sleep $TIME'm' &
echo $! >> "${SLEEP_PID_FILE}"
fg
BEEP="/usr/share/sounds/freedesktop/stereo/complete.oga"
paplay $BEEP
notify-send "Next Session" "Press <Ctrl><Shift><s> to run the script again"
然后你可以用类似的东西找到当前经过的时间:
notify-send "Already running for $(($(date +%s)-$(date -d"$(ps -o lstart= -p$(< "${SLEEP_PID_FILE}"))" +%s))) seconds..."