如何在bash中使用`wait`和`WSTOPPED`?

时间:2014-03-12 03:47:16

标签: git bash

假设父进程产生了几个子进程,这些进程在某些时候自行停止(尚未终止)。我希望父母wait为其所有孩子停止,这样他们就可以一步一步地工作。

这可能是一个XY问题,所以如果有更好的方法,我会全神贯注。 :)

我想为冲突构建一个协作git mergetool。

我有一个父进程,它为每个冲突文件生成一个子进程。我遗失的那篇文章是“等待所有孩子被阻止”。我怎么能这样做?

#parent.sh
# For each file in conflicting state
for f in `git ls-files --unmerged | cut -f2 | sort -u`
do
  git mergetool --tool=collaborate --no-prompt "$f" &
done

# Wait for all children to be STOPPED
wait # WSTOPPED? Not sure how to do this.

echo "All files uploaded. Visit www.example.com/abc123 to collaborate."
read -rsp $'Press enter to apply changes.\n'

# Continue all child processes.
kill -SIGCONT childpids? Need a list...

wait
echo "Finished!"

子进程必须以锁步方式工作。

#collaborate-mergetool.sh
BASE=$1
LOCAL=$2
REMOTE=$3
MERGED=$4

# TODO curl POST files to server

# When the four files are uploaded:
#   STOP this process and wait for siblings.
kill -SIGSTOP $$

# Download patch from server
# TODO curl GET "$filename".patch from server

# TODO apply patch

1 个答案:

答案 0 :(得分:0)

试试这个:

# instead of using wait, poll all child processes and detect those in a stopped state
while true ; do
  sleep 1
  N_CHILDREN=`jobs | wc -l`
  N_STOPPED=`jobs -s | wc -l`
  [ $N_CHILDREN == $N_STOPPED ] && break
done

使用shell sleep,您只能以一秒的粒度进行轮询。

如果您还有其他不想等待的子流程,则需要获得更多创意并解析内置作业的输出:

STOPPED_JOBS_PIDS=`jobs -sl | awk '{print $2}'`
# Compare to my list, etc...

在某些情况下,这可能会干扰shell本身的操作。

在这种情况下,您可能需要轮询ps的输出:

...
# Get the 'stat' column and look for a T, filter by my child processes of interest
git mergetool ... & PID1=$!
git mergetool ... & PID2=$!  # etc
...
while ...
  N_CHILDREN=2 # number of processes
  N_STOPPED=`ps -o pid -o stat -p PID1 $PID2 | tail -n +2 | awk '{print $2}' | grep T | wc -l`
...

此处,STAT列指示进程是在运行(R),休眠(S)还是停止(T)或僵尸或其​​他状态。