【问题标题】:wait child process but get error: 'pid is not a child of this shell'等待子进程但得到错误:'pid 不是这个 shell 的子进程'
【发布时间】:2011-11-08 09:58:35
【问题描述】:

我写了一个脚本从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

【问题讨论】:

  • 一个好问题,我得到了完全相同的错误。我启动了 96 个后台作业并等待它们。 96 个中的 4 个给了我“pid 28991(这个数字是随机子 PID 为例)不是这个 shell 的孩子”。我假设等待命令不是万无一失的。我会做一些挖掘工作。

标签: linux shell wait


【解决方案1】:

只需找到您要等待的进程的进程 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

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

【讨论】:

  • 聪明的把戏!您可以像这样等待,然后在该过程完成后启动脚本。
  • 不太好,如果每个计算机程序都使用这样的轮询,那将是一件非常糟糕的事情:)
  • 我将无法获取子进程的退出代码
  • 整洁。我不敢相信在任何地方都没有标准工具可以做到这一点......我制作了一个更简单的 shell 脚本,名为waitpid,基本上就是这样一个:while [ -e /proc/$1 ]; do sleep 1; done...
【解决方案2】:

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

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

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

【讨论】:

  • 尽管如此,您可以检查一下这种思路,例如在两个位置(以及脚本的顶层!)打印 $BASHPID、$$、$BASH_SUBSHELL
【解决方案3】:

如果你在某种容器中运行它,条件apparently can be caused by a bug in bash that is easier to encounter in a containerized envrionment

根据我对the bash source 的阅读(特别是在bash-4.2/jobs.c 中查看RECYCLES_PIDSCHILD_MAX 周围的cmets),看起来他们在努力优化对后台作业的跟踪时,使自己容易受到PID 别名的影响(新流程可能会掩盖旧流程的状态);为了缓解这种情况,他们修剪了他们的后台进程历史(显然是 POSIX 要求的?)。如果你碰巧想在一个修剪过的进程上wait,shell 在历史记录中找不到它,并假设这意味着它从来不知道它(即它“不是这个 shell 的孩子” )。

【讨论】:

    猜你喜欢
    • 2018-07-05
    • 2014-11-08
    • 1970-01-01
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多