Skip to content

Instantly share code, notes, and snippets.

@hell0again
Last active July 29, 2020 10:17
Show Gist options
  • Save hell0again/f5f3064ad1ea6c5c7308 to your computer and use it in GitHub Desktop.
Save hell0again/f5f3064ad1ea6c5c7308 to your computer and use it in GitHub Desktop.
bashで並列処理
#!/bin/sh
# - (...) はサブプロセス実行
# - & をつけるとコマンドをバックグラウンドプロセスとして起動する
# - wait ですべてのバックグラウンドプロセスを待機
# - waitにプロセスidを渡すと指定したプロセスが終了するまで待機したうえで指定プロセスの戻り値を返す
# - プロセスidを渡さない場合、すべての子プロセスを待つが終了ステータスはつねに0になる。
# - 子プロセスが0以外を返しても親プロセスはそれを検知できないので子プロセスの死亡を見て親プロセスを殺すのが難しい
# - プロセスidを複数渡すことはできない
(
sleep 1
echo "exit first with 1"
exit 1
)&
FIRST=$!
(
sleep 2
echo "exit second with 2"
exit 2
)&
SECOND=$!
wait $FIRST && wait $SECOND &&:
ST=$?
[ ${ST} -ne 0 ] && wait && exit ${ST}
# && だと1項目が0以外だと2項目以降は評価されない。
# つまり wait $FIRST && wait $SECOND みたいな形だとfirstが0以外を返した時点で「終了が確定」する。
# ただし終了が確定してもsecondのwaitを評価しないので他の子プロセスの実行が止まらなくなってしまう。
# なので改めてpid指定なしのwaitで残りの子も待つ。
# そうしないと先に親が死んで後で残りの子が死ぬ、みたいなことが起きてしまう。
#!/bin/sh
# いちいち変数名をつけたくないので配列に置き換え
# ついでにC-cを受付
trap '[ 0 -lt $(jobs | wc -l) ] && kill -HUP $(jobs -p)' EXIT
wait_for_all(){
local st=0
for pid in $@; do
wait ${pid} &&:
(exit $?) && (exit ${st}) &&:; st=$?
done
[ ${st} -ne 0 ] && exit ${st}
}
PIDS=()
(
sleep 1
echo "exit first with 1"
exit 1
)&
PIDS+=($!)
(
sleep 2
echo "exit first with 2"
exit 2
)&
PIDS+=($!)
wait_for_all ${PIDS[@]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment