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
wait child process but get error: 'pid is not a child of this shell'
提问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_PIDS
and CHILD_MAX
in 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 wait
on 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_MAX
在bash-4.2/jobs.c
),它看起来像在他们的努力,以优化他们的后台作业跟踪,他们离开自己脆弱的PID别名(其中一个新的进程可能会掩盖一个旧的状态); 为了缓解这种情况,他们修剪了他们的后台进程历史记录(显然是 POSIX 要求的?)。如果您碰巧想要wait
一个修剪过的进程,shell 无法在历史记录中找到它,并假定这意味着它从来不知道它(即,它“不是这个 shell 的子进程”)。