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
,并且先前版本可以是11518
或31518
。 在这种情况下,只需匹配4个数字,进程ID就会产生3个匹配,因为1518
在11518
之内。 胡萝卜匹配单词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
,你必须用cat
或gedit
等显示它们。
zenity
是一个很好的小程序,用于显示从bash到GUI
(图形用户界面)(即桌面)的对话框和表单。 消息文本继续说明上一个锁定屏幕计时器已终止。 。 这允许用户开始新的计时器倒计时或简单地取消。 本质上,第二次调用脚本并中止是如何杀死已经运行的第一个脚本。
kill "$PREVIOUS"
这会简单地杀死我们想要做的以前运行的版本,无论我们是否开始新的lock-screen-timer
倒计时。 这与原始问题大不相同,因为我们将两个神秘命令的结果放入名为$PREVIOUS
的单个变量中。