Bash脚本如何杀死已经运行的“睡眠”版本?

编辑从下面的评论我写了一个令人困惑/误导的介绍,所以我重写它。

我有一个名为“ 锁定屏幕计时器 ”的bash脚本,可以在桌面上单击。 30分钟后,它锁定屏幕,用户必须输入密码才能解锁屏幕。 但是,如果用户改变主意,或者他们想要重置计时器,他们应该能够再次单击桌面快捷方式,它应该杀死正在睡觉和倒计时的先前正在运行的作业。

到目前为止,我已经做了一些试验和错误,并且遇到了障碍。

相关的代码段是:

pgrep tv-timer > ~/tv-timer.log PID=$$ # Current Process ID 

使用cat ~/tv-timer.log

 16382 20711 

其中一个等于上面的“$ PID”,但另一个是以前运行的副本,我想使用kill #####

找出哪一个“$ PID”并杀死它的最佳方法是什么?

第一次运行脚本时,只有一个条目等于“$ PID”,我不想杀死它。

谢谢你的帮助!


建议的副本( 防止重复脚本同时运行 )是进程中的问题。 接受的答案很长且很复杂,涉及包装脚本和/或多行代码。

这里寻求的解决方案是一行新代码!

事实上,这里接受的选择答案是基于重复的OP尝试那里没有工作!

请改变行:

 pgrep tv-timer | grep -v $$ > ~/tv-timer2.log 

进入这个:

 pgrep tv-timer | grep -v ^$$$ > ~/tv-timer2.log 

事实上,如果一个电视计时器的话题有,例如,PID = 26019并且应该是$ 6019,那么grep会产生一个空字符串,这不是你想要的。

花了很多时间跟着白兔进入各种替代宇宙,我发现以下是唯一可靠的方法:

 # If called a second time, kill the first version already running kill $(pgrep -f "${0##*/}" | grep -v ^$$) 

如果您有兴趣测试这个,请参阅Ask Ubuntu中的Lock Screen Timer代码:( 应用程序将在Ubuntu设定的时间后锁定屏幕 )

生产版本代码段(TL; DR)

来自lock-screen-timer程序的相关代码片段如下:

 # Check if lock screen timer already running pID=$(pgrep -f "${0##*/}") # All PIDs matching lock-screen-timer name PREVIOUS=$(echo "$pID" | grep -v ^"$$") # Strip out this running copy ($$$) if [ $PREVIOUS != "" ]; then zenity --info --title="Lock screen timer already running" --text="Previous lock screen timer has been terminated." kill "$PREVIOUS" fi 

pgrep -f "${0##*/}"

这将查找所有出现的相同命名的正在运行的程序ID ${0##*/} 。 尽管可执行文件名为~/bin/lock-screen-timer但桌面快捷方式用于调用它。 这可以命名为“锁定屏幕定时器”或“锁定屏幕定时器”或“提醒我洗衣周期”。 它不能像原始问题那样硬编码到程序中。

生成的进程ID列表放在变量$pID

echo "$pID" | grep -v ^"$$"

这将获取$pID的内容(所有正在运行的lock-screen-timer ,或者它重命名为桌面快捷方式),并使用管道( | )字符将进程ID的列表$pID到下一个命令中。

下一个命令grep -v删除与$$匹配的进程ID,这是当前正在运行的进程ID。 胡萝卜( ^ )告诉grep匹配整个单词而不是字符串。 例如,当前进程id可以是1518 ,并且先前版本可以是1151831518 。 在这种情况下,只需匹配4个数字,进程ID就会产生3个匹配,因为151811518之内。 胡萝卜匹配单词1518 <> 11518 。 在进程id列表中,单词由空格(在变量中)或新行字符ps -aux (当ps -aux命令在屏幕上显示它们时)。

这两个命令的结果是先前运行的lock-screen-timer脚本的进程ID。 进程ID放入变量$PREVIOUS 。 如果没有先前的ID,则该值将为“”(空字段)。

if [ $PREVIOUS != "" ]; then

这测试$PREVIOUS是否不等于( != )空/空字段"" 。 显然,如果我们有一个,我们只能杀死以前运行的进程ID!

zenity --info --title="Lock screen timer already running" ...

运行桌面快捷方式时,您无法将消息echo给用户,因为GUI不会显示它们。 它们最终出现在/var/log/syslog ,你必须用catgedit等显示它们。

zenity是一个很好的小程序,用于显示从bash到GUI (图形用户界面)(即桌面)的对话框和表单。 消息文本继续说明上一个锁定屏幕计时器已终止。 。 这允许用户开始新的计时器倒计时或简单地取消。 本质上,第二次调用脚本并中止是如何杀死已经运行的第一个脚本。

kill "$PREVIOUS"

这会简单地杀死我们想要做的以前运行的版本,无论我们是否开始新的lock-screen-timer倒计时。 这与原始问题大不相同,因为我们将两个神秘命令的结果放入名为$PREVIOUS的单个变量中。