我正在使用 docker 容器交互式 shell 在 shell 上执行命令。
e.g. docker exec -i docker_container_name sh
然后我在这个交互式 shell 上启动命令。现在,如果我想终止这个交互式 shell 和在其上运行的命令,该怎么做?
我尝试向交互式 shell 发送
kill -9 shell_pid or kill -s 15 shell_pid
信号。然而,在这种情况下,交互式 shell 被终止,但在交互式 shell 上运行的命令仍然存在,并成为孤儿进程。
请让我知道如何杀死运行在其上的命令的交互式 shell。
您应该先获取子进程,然后再杀死 shell 并杀死它们
CPIDS=`pgrep -P $shellpid` # gets pids of child processes
kill -9 $shellpid
for cpid in $CPIDS ; do kill -9 $cpid ; done
或者(这不太安全,因为,如果在 shell 中运行一系列命令,则可能会在这两个终止命令之间调用下一个命令)
pkill -TERM -P $shellpid # sends TERMINATE signal to children
kill -9 $shellpid
对于 bash,最好使用的信号是
SIGHUP
。从docs,解释如下:
SIGHUP 默认退出 shell。交互式 shell 会向所有正在运行或已停止的作业发送 SIGHUP...
SIGHUP 的信号值为 1,因此您可以使用以下命令来结束交互式 bash shell:
kill -1 shell_pid
使用此方法,您不必去追踪 shell 的所有子进程,因为它会自行执行此操作。
此外,至于为什么使用 SIGKILL 或 SIGTERM 也没有终止子进程,同一文档对 SIGTERM 有解释:
在没有任何陷阱的情况下,交互式 Bash shell 会忽略 SIGTERM 和 SIGQUIT。 SIGINT 被捕获并处理,如果作业控制处于活动状态,SIGTTIN、SIGTTOU 和 SIGTSTP 也会被忽略。当键盘生成时,作为命令替换结果运行的命令也会忽略这些信号。
最后,SIGKILL无法杀死子进程,因为SIGKILL信号对于任何接收到该信号的进程来说都是“致命的”。除了从进程表中 RIP 以及它生成的任何线程之外,无法以任何其他方式处理它。