有没有办法调用子进程,以便它及其所有后代发送一个中断,就像你Ctrl-C前台任务一样?我正在尝试杀死一个调用一个长期运行的孩子的启动器脚本.我已经尝试过kill -SIGINT $child(它不会向其后代发送中断,因此是无操作)和kill -SIGINT -$child(在交互式调用时有效但在脚本中运行时无效).
这是一个测试脚本.长期运行的脚本是test.sh --child.当你打电话时test.sh --parent,它会调用test.sh --child &然后尝试杀死它.如何让父母成功杀死孩子?
#!/bin/bash
if [ "$1" = "--child" ]; then
sleep 1000
elif [ "$1" = "--parent" ]; then
"$0" --child &
for child in $(jobs -p); do
echo kill -SIGINT "-$child" && kill -SIGINT "-$child"
done
wait $(jobs -p)
else
echo "Must be invoked with --child or --parent."
fi
Run Code Online (Sandbox Code Playgroud)
我知道你可以修改长时间运行的子trap信号,将它们发送到它的子进程,然后等待(从
Bash脚本杀死Ctrl + C上的背景(大)子),但有没有办法不修改子脚本?
vvo*_*vvo 11
对于任何想知道的人,这是你如何在后台启动孩子并在ctrl + c上杀死他们:
#!/usr/bin/env bash
command1 &
pid[0]=$!
command2 &
pid[1]=$!
trap "kill ${pid[0]} ${pid[1]}; exit 1" INT
wait
Run Code Online (Sandbox Code Playgroud)
somecommand &
Run Code Online (Sandbox Code Playgroud)
返回孩子的pid $!
somecommand &
pid[0]=$!
anothercommand &
pid[1]=$!
trap INT " kill ${pid[0]} ${pid[1]}; exit 1"
wait
Run Code Online (Sandbox Code Playgroud)
我会从这个模型开始,而不是使用bash作业控制(bg,fg,jobs).通常,init继承并获取孤立进程.你想解决什么问题?
也来自 info bash
To facilitate the implementation of the user interface to job control,
the operating system maintains the notion of a current terminal process
group ID. Members of this process group (processes whose process group
ID is equal to the current terminal process group ID) receive keyboard-
generated signals such as SIGINT. These processes are said to be in
the foreground. Background processes are those whose process group ID
differs from the terminal's; such processes are immune to keyboard-gen?
erated signals.
Run Code Online (Sandbox Code Playgroud)
因此,bash通过进程组ID区分后台进程与前台进程.如果进程组id等于进程id,则该进程是前台进程,并在收到SIGINT信号时终止.否则它将不会终止(除非它被困).
你可以看到进程组ID与
ps x -o "%p %r %y %x %c "
Run Code Online (Sandbox Code Playgroud)
因此,当您&在脚本中运行后台进程(with )时,它将忽略该SIGINT信号,除非它被捕获.
但是,你仍然可以杀死与其他信号,如子进程SIGKILL,SIGTERM等等.
例如,如果将脚本更改为以下内容,则会成功终止子进程:
#!/bin/bash
if [ "$1" = "--child" ]; then
sleep 1000
elif [ "$1" = "--parent" ]; then
"$0" --child &
for child in $(jobs -p); do
echo kill "$child" && kill "$child"
done
wait $(jobs -p)
else
echo "Must be invoked with --child or --parent."
fi
Run Code Online (Sandbox Code Playgroud)
输出:
$ ./test.sh --parent
kill 2187
./test.sh: line 10: 2187 Terminated "$0" --child
Run Code Online (Sandbox Code Playgroud)