在我的工作场所,我们有一个由 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
这个问题不是你的问题的关键,但它是需要记住的事情。