如何在不关闭终端的情况下终止在终端中运行的脚本(Ctrl + C 不起作用)?

bec*_*cko 45 bash scripts

我编写了一个 bash 脚本,它调用其他几个程序并执行一堆命令。我从终端运行这个脚本。现在我想杀死脚本。

Ctrl + C有时按下并不会切断它,我认为是因为有时脚本正在执行另一个程序,并且出于某种原因终止信号不起作用。

但是,如果我关闭终端窗口,它会杀死脚本。

有什么我可以做的(键盘组合),类似于关闭终端窗口,而不实际关闭终端窗口(我不想丢失命令历史记录、当前目录、输出历史记录等)?

mur*_*uru 43

你有几个选择。一种是停止脚本(CtrlZ),获取脚本的PID并发SIGKILL送给进程组。

在 shell 中执行命令时,它启动的进程及其所有子进程都属于同一个进程组(在本例中为前台进程组)。要向该组中的所有进程发送信号,请将其发送给进程领导者。对于kill命令,进程领导者表示为:

kill -PID
Run Code Online (Sandbox Code Playgroud)

PID脚本的进程ID在哪里。

例子:

考虑一个test.sh启动一些进程的脚本。假设您在 shell 中运行它:

$ ./test.sh
Run Code Online (Sandbox Code Playgroud)

在另一个终端,

$ 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)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,要向由 创建的进程组发送信号test.sh,您可以执行以下操作:

kill -INT -17802
Run Code Online (Sandbox Code Playgroud)

-INT用于发送SIGINT,所以这个命令相当于CtrlC在终端上按下。发送SIGKILL

kill -KILL -17802
Run Code Online (Sandbox Code Playgroud)

如果您无法打开另一个终端,您只需要停止脚本。如果可以,请使用pgrep查找PID。

脚本启动的命令之一可能是 trapping SIGINT,这可能CtrlC是无效的原因。但是,SIGKILL不能被困,通常是不得已的选择。您可能想尝试SIGTERM( -TERM) 后再进行杀戮。无论是SIGKILLSIGTERM可以被设置为快捷键的方式SIGINT是。

如果您的脚本不包含 shebang 行,则所有这些都没有实际意义。从这个 SO 答案

通常父 shell 猜测脚本是为同一个 shell 编写的(最小的类似 Bourne 的 shell 使用 /bin/sh 运行脚本,bash 将它作为 bash 子进程运行)......

因此,在执行脚本时,您将找不到以脚本命名的进程(或命令行中具有脚本名称的进程)并且pgrep会失败。

始终使用shebang线。


Har*_*ris 6

如果您知道与脚本关联的进程,您可以使用以下命令找到它们的 PID

 ps -A
Run Code Online (Sandbox Code Playgroud)

然后使用PID号杀死相应的进程使用

 kill -9 PID_Number
Run Code Online (Sandbox Code Playgroud)