编辑根据下面的评论,我写了一个令人困惑/误导性的介绍,所以我正在重写它。
我有一个名为“锁屏定时器“可以在桌面上单击。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
,而上一个版本可能是11518
,21518
或31518
。在这种情况下,只要匹配 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
,您必须使用cat
或gedit
等来显示它们。
zenity
是一个不错的小程序,用于将对话框和表单从 bash 显示到GUI
(图形用户界面),又称桌面。消息文本继续说之前的锁屏计时器已终止。。这允许用户启动新的计时器倒计时或直接取消。本质上,第二次调用脚本并中止就是终止已在运行的第一个脚本的方法。
kill "$PREVIOUS"
这只是终止了之前正在运行的版本,无论我们lock-screen-timer
是否开始新的倒计时,我们都希望这样做。这与原始问题有很大不同,因为我们将两个神秘命令的结果放入了名为的单个变量中$PREVIOUS
。