如何在行为不当的应用程序退出后自动关闭其留下的进程?

如何在行为不当的应用程序退出后自动关闭其留下的进程?

有些应用程序不会完全退出,留下其进程。我发现的一个例子是福昕阅读器。当然,理想的情况是报告错误并修复应用程序,但有时这是不可能的。例如,对于福昕阅读器,开发人员表示他们不再对当前版本进行任何修复,因为他们正在进行完全重写。

我希望这样当我退出应用程序时,它留下的进程会自动关闭(当然不会创建更多留下的进程)。我怎么做?

答案1

我相信最简单的方法是通过脚本启动程序并建立trap整个kill进程组:

#!/bin/bash
trap "kill -9 -- -$$" ERR EXIT
/path/to/gui-programm

它是如何工作的?

Atrap是一个 shell 内置命令,如果脚本收到一个(或多个)信号,它就会执行特定命令。在这种情况下,EXIT 代表正常退出(即关闭 GUI 程序),ERR 代表任何错误(例如CTRL+C,或者 Foxit 被其他原因杀死)。参考:man signalman bash

使用的命令是kill,其中-9发送 SIGKILL。kill可以通过向 PID 添加减号来终止单个进程,从而kill <pid>作用于整个进程组(即进程及其所有子进程和分支)。--需要这样,以便以下参数不会被解释为标志。即kill -9 -- -$pid 会杀掉一段时间的进程组。

$$只是当前 shell 脚本的 PID。 GUI程序是脚本的子进程,并且GUI程序本身的子进程也是链接到作为源的脚本的进程组的一部分。

如果你想测试它,我建议使用多次睡眠:

 #!/bin/bash
 #test script for kill via trap
 trap "kill -9 -- -$$" ERR EXIT
 for (( i=1 ; i<=100 ; i++ )) ; do
   sleep 120
 done
 /path/to/gui-command

现在,如果退出 GUI 命令,所有睡眠都会消失。如果您注释掉陷阱部分,它们将保留下来。


为了确保trap在子进程失败时也执行 ,需要通过 继承set -E

#!/bin/bash
set -E
trap "kill -9 -- -$$" ERR EXIT
/path/to/gui-programm

答案2

一种方法是从脚本启动应用程序,而不是直接启动应用程序。应用程序运行时其输出通过管道传输到临时文件。然后,针对该文件通过管道运行 tail 到 fifo。接下来 grep 针对 fifo 运行。当找到某些文本时,尾部进程被杀死,fifo关闭,应用程序进程被强制杀死并删除临时文件。

应选择文本,使其成为应用程序退出时输出的最后一个文本(如果从命令行启动应用程序,您可以看到该文本)。例如,当我关闭 FoxitReader 时,它输出的最后一个文本是“CJS_Module::ExitEnumJSPlugThread”。

以下示例脚本展示了它如何与 FoxitReader 配合使用,并且可以轻松适应其他应用程序:

#!/bin/bash
file=/tmp/foxit.txt
YOURPATH/foxitsoftware/foxitreader/FoxitReader "$@" &> $file &
foxitpid=$!
fifo=/tmp/tmpfifo.$$
mkfifo $fifo || exit 1
tail -f $file >$fifo &
tailpid=$!
grep -m 1 "CJS_Module::ExitEnumJSPlugThread" $fifo
kill $tailpid
rm $fifo
kill -9 $foxitpid
rm -f $file
exit 0

答案3

根据@mcarans的回答,您可以微调福昕阅读器安装目录下的启动脚本:

<INSTALLPATH>/foxitreader/FoxitReader.sh

将此脚本修改为(记得检查 <INSTALLPATH>):

#!/bin/bash
selfpath="<INSTALLPATH>/foxitreader"
file=/tmp/foxit.txt
"$selfpath/FoxitReader" "$@" &> $file &
foxitpid=$!
fifo=/tmp/tmpfifo.$$
mkfifo $fifo || exit 1
tail -f $file >$fifo &
tailpid=$!
grep -m 1 "~CJS_Module()" -m 1 "CJS_Module::ExitEnumJSPlugThread()" $fifo
kill $tailpid
rm $fifo
kill -9 $foxitpid
rm -f $file
exit 0

保存它,一切就都准备好了。您可以像往常一样双击PDF文件并将其关闭,并且不会有任何剩余进程。

相关内容