如何终止终端而不是 tty 会话的所有子进程?

如何终止终端而不是 tty 会话的所有子进程?

在我的工作场所,我们有一个由 SLURM 管理的高性能计算集群。

有些人的作业会产生很多进程,但作为一个联合体,它们只是一个作业。他们编写的顶层控制器也很糟糕,因此 SIGINT 会导致子进程变成僵尸进程。

由于这种环境的性质,期望他们解决这个问题是不合理的(没有实际的正当理由)。

因此,我尝试制作一个提交包装器,它在作业结束时将终止所有子进程。

ps默认情况下,抓取与当前 tty 会话相关的所有进程。但是,SLURM 做了一些愚蠢的事情,它ps不只是抓取此作业的此任务的进程,还抓取其他任务的进程,因此每当一个作业终止时,它就会终止物理节点上的所有内容。

所以,我如何获取/终止所有属于当前的bash 脚本?

答案1

当前进程(脚本进程或 shell,无论哪种情况)存储在 $$ 中。使用该 PID,您可以使用带有 -P 标志的 pgrep 命令: pgrep -P $$
获取父 PID 为的所有 PID 的列表$$

这是一个非常简单的概念验证脚本:

#!/bin/bash

curpid="$$"
#launch 2 useless child processes
cat /dev/random > /dev/null &
cat /dev/random > /dev/null &
cpid=`pgrep -P $curpid`  && echo "$(basename $0) pid: $curpid; child pids:" $cpid
#kill the child pids
kill $cpid
# check if any child pids still exist
newcpid=`pgrep -P $curpid`
if [ $? -ne "0" ] || [ "$newcpid" != "" ]; then
  echo "no child pids left..."
else
  echo $newcpid
fi

输出:

{0} 02:34:57] $ ./test3.sh 
test3.sh pid: 7015; child pids: 7016 7017
./test3.sh: line 12:  7016 Terminated              cat /dev/random > /dev/null
./test3.sh: line 12:  7017 Terminated              cat /dev/random > /dev/null
no child pids left...

如果你以其他用户身份(例如 sudo)启动任何子进程,那么即使你是父进程,你也可能没有权限终止该进程。如果你更改了

cat /dev/random > /dev/null &

行至

sudo cat /dev/random > /dev/null &

您将无法终止该进程(假设您最初使用普通用户帐户启动该脚本)

修改后的脚本(以 root 身份运行一个子脚本并在最后输出差异信息):

#!/bin/bash

curpid="$$"
#launch 2 useless child processes
cat /dev/random > /dev/null &
sudo cat /dev/random > /dev/null &
cpid=`pgrep -P $curpid`  && echo "$(basename $0) pid: $curpid; child pids:" $cpid
#kill the child pids
kill $cpid
sleep 0.5
#check on children
for i in $cpid; do
  echo -n "PID: $i; Orig PPID: $curpid; Cur PPID: "`/usr/bin/ps --ppid $i | grep -Eo '[0-9]{3,}'`
  echo
done

其中一个子程序以 root 身份运行的输出:

[{0} 02:53:51] $ ./test3.sh 
test3.sh pid: 8144; child pids: 8145 8146
./test3.sh: line 9: kill: (8146) - Operation not permitted
./test3.sh: line 10:  8145 Terminated              cat /dev/random > /dev/null
PID: 8145; Orig PPID: 8144; Cur PPID: 
PID: 8146; Orig PPID: 8144; Cur PPID: 8150

以 root 身份启动的子 PID 不再将初始脚本视为其父级,而是将其视为使用 sudo 调用创建的子 shell。 的输出ps auxf
也清楚地显示了这一点:

root      8146  0.0  0.0 244996  7444 pts/2    S    02:54   0:00 sudo cat /dev/random
root      8150  0.0  0.0 113828   744 pts/2    S    02:54   0:00  \_ cat /dev/random

这个问题不是你的问题的关键,但它是需要记住的事情。

相关内容