2015-04-02 75 views
1

我构建了一个shell脚本,睡眠指定的分钟数并在完成时显示通知。获取睡眠命令在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" 

我使用的代码的开始的文件为基础的方法执行防止程序的多个实例。当一个用户想要在另一个实例运行时运行脚本时,它会显示脚本已经在运行的通知。

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} 

现在我想将文本添加到,告诉多少秒都留在我的壳睡眠命令通知的最后删除临时文件脚本结束。 (改变已经运行通知如下)

notify-send "Already Running" $SECONDS 

为了实现我自己控制的睡眠命令while循环会影响计算机的整体性能。我认为sleep命令是一个更好的选择,因为它通过将自身发送到进程队列中的等待状态来优化进程。 有什么办法可以解决这个问题吗?

+0

这种哇,这么多的文字,代码太少 – 2015-04-02 08:37:34

回答

2

存储脚本应该在锁定文件中结束的时间。

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杀手之后)。

+1

顺便说一下,使用'EXIT'陷阱时,不需要在脚本末尾显式删除锁定文件。 – tripleee 2015-04-02 09:49:46

+0

不错的一个。作品完美。虽然有一个修改,但notify-send命令不能接受一个负数作为它认为的第二个参数,就好像提供了一个命令行选项一样:所以对代码中的第四行稍作修改: 'notify-send“Already running” “$(($ endtime - $(date +%s)))seconds”' – 2015-04-02 09:49:51

+0

然后剩余的-13秒也不是有效的选项名称。也许把它改为'“剩下的秒数:$(($ endtime - $(date +%s)))”'...但是如果结果是否定的,我想它应该已经完成​​了。 – tripleee 2015-04-02 09:51:56

0

我认为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..."