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

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

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

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

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

相关代码片段为:

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

使用cat ~/tv-timer.log

16382
20711

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

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

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

感谢您的帮助!


建议的重复(防止重复脚本同时运行)是一个问题父母孩子流程。可接受的答案很长且很复杂,涉及包装器脚本和/或多行代码。

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

确实接受答案这是基于重复的 OP 尝试那里不行!

答案1

请更改此行:

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

变成这样:

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

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

答案2

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

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

如果你有兴趣测试这个,请参阅Lock Screen Timer代码询问 Ubuntu在: (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 列表传送到下一个命令中。|

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

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

if [ $PREVIOUS != "" ]; then

这将测试 是否$PREVIOUS不等于 ( !=) 一个 null / 空字段""。显然,如果我们有一个之前正在运行的进程 ID,我们只能终止它!

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

运行桌面快捷方式时,您无法echo向用户发送消息,因为 GUI 不会显示它们。它们最终会显示在 中/var/log/syslog,您必须使用catgedit等来显示它们。

zenity是一个不错的小程序,用于将对话框和表单从 bash 显示到GUI(图形用户界面),又称桌面。消息文本继续说之前的锁屏计时器已终止。。这允许用户启动新的计时器倒计时或直接取消。本质上,第二次调用脚本并中止就是终止已在运行的第一个脚本的方法。

kill "$PREVIOUS"

这只是终止了之前正在运行的版本,无论我们lock-screen-timer是否开始新的倒计时,我们都希望这样做。这与原始问题有很大不同,因为我们将两个神秘命令的结果放入了名为的单个变量中$PREVIOUS

相关内容