Linux 等待子进程但得到错误:“pid 不是这个 shell 的子进程”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8048628/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 07:05:46  来源:igfitidea点击:

wait child process but get error: 'pid is not a child of this shell'

linuxshellwait

提问by henshao

I write a script to get data from HDFS parrallel,then I wait these child processes in a for loop, but sometimes it returns "pid is not a child of this shell". sometimes, it works well。It's so puzzled. I use "jobs -l" to show all the jobs run in the background. I am sure these pid is the child process of the shell process, and I use "ps aux" to make sure these pids is note assign to other process. Here is my script.

我写了一个脚本从 HDFS 并行获取数据,然后我在 for 循环中等待这些子进程,但有时它返回“pid is not a child of this shell”。有时,它运作良好。它是如此的困惑。我使用“jobs -l”来显示在后台运行的所有作业。我确定这些 pid 是 shell 进程的子进程,并且我使用“ps aux”来确保这些 pid 是注释分配给其他进程的。这是我的脚本。

PID=()
FILE=()
let serial=0

while read index_tar
do
        echo $index_tar | grep index > /dev/null 2>&1

        if [[ $? -ne 0 ]]
        then
                continue
        fi

        suffix=`printf '%03d' $serial`
        mkdir input/output_$suffix
        $HADOOP_HOME/bin/hadoop fs -cat $index_tar | tar zxf - -C input/output_$suffix \
                && mv input/output_$suffix/index_* input/output_$suffix/index &

        PID[$serial]=$!
        FILE[$serial]=$index_tar

        let serial++

done < file.list

for((i=0;i<$serial;i++))
do
        wait ${PID[$i]}

        if [[ $? -ne 0 ]]
        then
                LOG "get ${FILE[$i]} failed, PID:${PID[$i]}"
                exit -1
        else
                LOG "get ${FILE[$i]} success, PID:${PID[$i]}"
        fi
done

回答by sehe

Either your while loop or the for loop runs in a subshell, which is why you cannot await a child of the (parent, outer) shell.

您的 while 循环或 for 循环在子 shell 中运行,这就是为什么您不能等待(父、外)shell 的子级的原因。

Editthis might happen if the while loop or for loop is actually

编辑这可能发生如果 while 循环或 for 循环实际上是

(a) in a {...}block (b) participating in a piper (e.g. for....done|somepipe)

(a) 在一个{...}区块中 (b) 参与一个吹笛者(例如for....done|somepipe

回答by Parvinder Singh

Just find the process id of the process you want to wait for and replace that with 12345 in below script. Further changes can be made as per your requirement.

只需找到您要等待的进程的进程 ID,然后在下面的脚本中将其替换为 12345。可以根据您的要求进行进一步的更改。

#!/bin/sh
PID=12345
while [ -e /proc/$PID ]
do
    echo "Process: $PID is still running" >> /home/parv/waitAndRun.log
    sleep .6
done
echo "Process $PID has finished" >> /home/parv/waitAndRun.log

/usr/bin/waitingScript.sh

/usr/bin/waitingScript.sh

http://iamparv.blogspot.in/2013/10/unix-wait-for-running-process-not-child.html

http://iamparv.blogspot.in/2013/10/unix-wait-for-running-process-not-child.html

回答by jhfrontz

If you're running this in a container of some sort, the condition apparently can be caused by a bug in bash that is easier to encounter in a containerized envrionment.

如果您在某种容器中运行它,这种情况显然可能是由 bash 中的一个错误引起的,该错误在容器化环境中更容易遇到

From my reading of the bash source(specifically see comments around RECYCLES_PIDSand CHILD_MAXin bash-4.2/jobs.c), it looks like in their effort to optimize their tracking of background jobs, they leave themselves vulnerable to PID aliasing (where a new process might obscure the status of an old one); to mitigate that, they prune their background process history (apparently as mandated by POSIX?). If you should happen to want to waiton a pruned process, the shell can't find it in the history and assumes this to mean that it never knew about it (i.e., that it "is not a child of this shell").

从我读的是bash源(特别是看到周围的意见RECYCLES_PIDS,并CHILD_MAXbash-4.2/jobs.c),它看起来像在他们的努力,以优化他们的后台作业跟踪,他们离开自己脆弱的PID别名(其中一个新的进程可能会掩盖一个旧的状态); 为了缓解这种情况,他们修剪了他们的后台进程历史记录(显然是 POSIX 要求的?)。如果您碰巧想要wait一个修剪过的进程,shell 无法在历史记录中找到它,并假定这意味着它从来不知道它(即,它“不是这个 shell 的子进程”)。