关于linux:如何在杀死Bash脚本时杀死当前命令

How to Kill Current Command When Bash Script is Killed

我目前有一个像这样的脚本。

1
2
3
4
5
# code

mplayer"$vid"

# more code

问题在于,如果该脚本被杀死,则mplayer进程将继续运行。我想知道如何做到这一点,以便杀死脚本也将杀死mplayer。

我不能使用exec,因为我需要在mplayer之后运行命令。

1
exec mplayer"$vid"

我能想到的唯一可能的解决方案是在后台生成它,然后等待它手动完成。这样,我可以获取它的PID并在脚本被杀死时将其杀死,而不是很优雅。我想知道这样做的"正确"或最佳方法是什么。


我能够测试我在评论中发布的prctl想法,而且似乎可行。您将需要编译以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<wyn>
#include"sys/prctl.h"
#include"stdlib.h"
#include"string.h"
#include"unistd.h"

int main(int argc, char ** argv){

  prctl(PR_SET_PDEATHSIG, atoi(argv[1]),0,0,0);

  char * argv0 = strdup(argv[2]);

  char * slashptr = strrchr(argv0, '/');
  if(slashptr){
    argv0 = slashptr + 1;
  }

   return execvp(argv0, &(argv[2]));



}
</wyn>

假设您已将上面的代码编译为一个名为" prun"的可执行文件,并且该文件位于您的路径中。假设您的脚本称为" foo.sh",并且它也在您的路径中。制作一个调用的package器脚本
prun 15 foo.sh

当package器脚本由于任何原因而终止时,即使

foo.sh也应获得SIGTERM。

注意:这是仅Linux的解决方案,显示的c源代码没有详细检查参数


感谢Mux的带领。看来,除了手动捕获信号外,没有其他方法可以在bash中执行此操作。这是最终的工作版本(注释过多)。

1
2
3
4
5
6
7
8
9
trap : SIGTERM SIGINT # Trap these two (killing) signals.  These will cause wait
                      # to return a value greater than 128 immediately after received.

mplayer"$vid" & # Start in background (PID gets put in `$!`)
pid=$!

wait $pid # Wait for mplayer to finish.
[ $? -gt 128 ] && { kill $pid ; exit 128; } ; # If a signal was recieved
                                              # kill mplayer and exit.

推荐人:
-陷阱:http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html


好吧,您可以简单地杀死进程组,这样整个进程树将被杀死,首先找出组ID

1
ps x -o "%p %r  %c" | grep <name>

然后像这样使用kill:

1
kill -TERM -<gid>

请注意过程组ID之前的破折号。还是单线:

1
kill -TERM -$(pgrep <name>)


(已更新),我想我了解您正在寻找的内容:

您可以通过产生一个新的终端来运行脚本来完成此任务:

1
gnome-terminal -x /path_to_dir_of_your_script/your_script_name

(或使用xterm -ekonsole -e代替gnome-terminal -x,具体取决于您所使用的系统)

因此,现在每当脚本结束/退出时(我假设脚本的某些部分具有exit 0exit 1),由于脚本完成,新生成的终端也将退出-这又会杀死在该新终端下产生的所有应用程序。

例如,我刚刚使用以下脚本测试了上述命令:

1
2
3
4
5
6
7
8
#!/bin/bash

gedit &
pid=$!
echo"$pid"

sleep 5
exit 0

如您所见,没有明确的调用来杀死新的gedit进程,但是无论如何,一旦脚本退出,应用程序(gedit)就会关闭。

(先前的回答:或者,如果您只是询问如何终止进程),这是一个简短示例,说明如何使用kill来完成该任务。

1
2
3
4
5
6
7
8
#!/bin/bash

gedit &
pid=$!
echo"$pid"

sleep 5
kill -s SIGKILL $pid

除非我误解了您的问题,否则您可以立即获取生成的进程的PID,而不必等到完成为止。


也许使用命令替换在子shell中运行mplayer"$vid"

1
$(mplayer"$vid")

我以此方式进行了测试:

tesh.sh:

1
2
3
#!/bin/sh
$vid ="..."
$(mplayer"$vid")
1
% test.sh

在单独的终端中:

1
% pkill test.sh

在原始终端中,mplayer停止,打印到stderr

1
2
Terminated
MPlayer interrupted by signal 13 in module: av_sync