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

Win*_*nix 5 bash scripts process

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

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

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

相关的代码片段是:

pgrep tv-timer > ~/tv-timer.log
PID=$$ # Current Process ID
Run Code Online (Sandbox Code Playgroud)

使用cat ~/tv-timer.log

16382
20711
Run Code Online (Sandbox Code Playgroud)

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

找出哪个 <> "$PID" 并杀死它的最佳方法是什么?

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

谢谢你的帮助!


所提出的重复(在的Sametime防止重复脚本运行)是内一个问题家长儿童的过程。接受的答案冗长而复杂,涉及包装脚本和/或多行代码。

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

实际上,这里的被接受的答案是基于重复的op尝试,不起作用!

Win*_*nix 2

在跟随白兔进入不同的平行宇宙花了很多时间后,我发现以下是唯一可靠的方法:

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

如果您有兴趣测试此功能,请参阅Ask UbuntuLock 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
Run Code Online (Sandbox Code Playgroud)

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

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

进程 ID 的结果列表被放入变量中$pID

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

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

下一个命令删除与当前正在运行的进程 IDgrep -v匹配的进程ID。$$胡萝卜 ( ^) 告诉 grep 匹配整个单词而不是字符串。例如,当前进程 id 可能是1518,先前版本可能是115182151831518。在这种情况下,只需匹配进程 id 的 4 位数字即可实现这 3 个匹配,因为1518位于11518. 胡萝卜与单词匹配,所以1518<> 11518。在进程 ID 列表中,单词由空格(在变量中)或换行符(当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