问题描述
我编写了一个bash脚本,调用其他几个程序并执行一堆命令。我从终端运行这个脚本。现在我要杀死脚本。
按Ctrl + C
有时不会削减它,我认为因为有时脚本正在执行另一个程序,并且由于某种原因,kill信号不起作用。
但是,如果我关闭终端窗口,它会杀死脚本。
有什么我能做的(键盘组合),类似于关闭终端窗口,而不是实际关闭终端窗口(我不想丢失命令历史,当前目录,输出历史等)?
最佳解决方法
你有几个选择。一种是停止脚本(Ctrl
Z
),获取脚本的PID并将SIGKILL
发送到进程组。
在shell中执行命令时,它启动的进程及其所有子进程都是同一process group(在本例中为前台进程组)的一部分。要向该组中的所有进程发送信号,请将其发送给进程负责人。对于kill
命令,进程负责人如下表示:
kill -PID
其中PID
是脚本的进程ID。
例:
考虑一个启动某些进程的脚本test.sh
。假设你在shell中运行它:
$ ./test.sh
在另一个终端,
$ pgrep test.sh
17802
$ pstree -ps `!!`
pstree -ps `pgrep test.sh`
init(1)───sshd(1211)───sshd(17312)───sshd(17372)───zsh(17788)───test.sh(17802)─┬─dd(17804)
├─sleep(17805)
└─yes(17803)
在这种情况下,要向test.sh
创建的进程组发送信号,您需要执行以下操作:
kill -INT -17802
-INT
用于发送SIGINT
,因此该命令相当于在终端上按Ctrl
C
。要发送SIGKILL
:
kill -KILL -17802
如果无法打开另一个终端,则只需停止脚本即可。如果可以,请使用pgrep
查找PID。
脚本启动的命令之一可能是捕获SIGINT
,这可能是Ctrl
C
无效的原因。但是,SIGKILL
不能被捕获,它通常是last-resort选项。在进行杀戮之前,你可能想尝试SIGTERM
(-TERM
)。 SIGKILL
或SIGTERM
都不能像SIGINT
那样设置为keyboard shortcut。
如果你的脚本不包含shebang行,那么这一切都没有实际意义。来自this SO answer:
Usually the parent shell guesses that the script is written for the the same shell (minimal Bourne-like shells run the script with /bin/sh, bash runs it as a bash subprocess) …
因此,在执行脚本时,您将找不到以脚本命名的进程(或在命令行中具有脚本名称的进程),并且pgrep
将失败。
总是使用shebang线。
次佳解决方法
如果您知道与脚本关联的进程,则可以使用它来查找其PID
ps -A
然后使用PID号来杀死相应的进程
kill -9 PID_Number