4

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

# code

mplayer "$vid"

# more code

问题是,如果这个脚本被杀死,mplayer 进程仍然存在。我想知道我怎么能做到这样杀死脚本也会杀死 mplayer。

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

exec mplayer "$vid"

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

4

5 回答 5

4

我能够测试我在评论中发布的 prctl 想法,它似乎有效。你需要编译这个:


#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]));



}

假设您已将上述内容编译为名为“prun”的可执行文件,并且它在您的路径中。假设您的脚本名为“foo.sh”,它也在您的路径中。制作一个调用的包装脚本

prun 15 foo.sh

当包装脚本因任何原因(甚至是 SIGKILL)终止时,foo.sh 应该得到 SIGTERM。

注意:这是一个仅限 linux 的解决方案,提供的 c 源代码没有详细检查参数

于 2012-11-06T18:18:05.290 回答
3

感谢 Mux 的领导。除了手动捕获信号外,似乎没有办法在 bash 中执行此操作。这是最终的工作(过度评论)版本。

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

于 2012-11-04T23:59:41.283 回答
2

(Updated) I think I understand what you are looking for now:

You can accomplish this by spawning a new terminal to run your script:

gnome-terminal -x /path_to_dir_of_your_script/your_script_name

(or use xterm -e or konsole -e instead of gnome-terminal -x, depending on what system you are on)

So now whenever your script ends / exits (I assume you have exit 0 or exit 1 in certain parts of the script), the newly spawned terminal will also exit since the script is finished - this will in turn also kill any applications spawned under that new terminal.

For example, I just tested the above command with this script:

#!/bin/bash

gedit &
pid=$!
echo "$pid"

sleep 5
exit 0

As you can see, there are no explicit calls to kill the new gedit process, but the application (gedit) closes as soon as the script exits anyway.

(Previous answer: alternatively, if you were simply asking about how to kill a process) Here's a short example of how you can accomplish that with kill.

#!/bin/bash

gedit &
pid=$!
echo "$pid"

sleep 5
kill -s SIGKILL $pid

Unless I misunderstood your question, you can get the PID of the spawned process right away instead of waiting until it finishes.

于 2012-11-04T18:16:02.460 回答
2

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

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

然后像这样使用 kill :

kill -TERM -<gid>

请注意进程组 ID 前的破折号。或单线:

kill -TERM -$(pgrep <name>)
于 2012-11-04T18:34:11.900 回答
0

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

$(mplayer "$vid")

我是这样测试的:

tesh.sh:

#!/bin/sh
$vid = "..."
$(mplayer "$vid")

% test.sh

在单独的终端中:

% pkill test.sh

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

Terminated
MPlayer interrupted by signal 13 in module: av_sync
于 2012-11-04T20:51:24.267 回答