シェルスクリプトを書いていたところ、wait
の思わぬ仕様に面食らってしまいました。
問題の発覚
Webアプリケーションのデプロイ処理で、多数のコマンドを呼び出す必要があったので、シェルスクリプトを書いてそれらをつなぎ合わせていました。そして、デプロイ処理を行うマシンのスペックに余裕があったので、並列でコマンドを実行させるようにしました。
#!/bin/sh
set -e
some_container_build_command &
some_database_seed_command &
wait
some_javascript_bundle_command
some_container_push_command
ところがある日のこと、DBのシードに失敗したにもかかわらず、set -e
でスクリプト全体が失敗することもないままコンテナのプッシュまで進行してしまったことが判明しました。
何が起きた?
調べてみると、wait
の挙動は以下のようなものでした(POSIX.1-2017)。
wait
(引数なし)→ 自身は0で終了する
wait [1個以上のpid...]
→ wait
自体の終了コードは、最後に与えたpid
のプロセスの終了コード(仮に最後のpid
が適切でなかった場合は127)
対策法
ということで、問答無用に成功するwait
オンリーはいうまでもなく、最後の1つの失敗しか検知できない複数表記というのも微妙なので、原始的にwait pid
を個数だけ連ねて対応することにしました。
#!/bin/sh
set -e
some_container_build_command &
container_build_pid=$!
some_database_seed_command &
seed_pid=$!
wait $container_build_pid
wait $seed_pid
some_javascript_bundle_command
some_container_push_command
終わりに
日常的に使っているコマンドにすら、想定しないような仕様があることも珍しくない。