りんごとバナナとエンジニア

エンジニア修行の記録

Jenkinsでシェルスクリプトを-eオプションなしで実行したい

最近Jenkinsを使い始めたが、Jenkins上でシェルスクリプトを書くと、特に何も指定していなくても #!/bin/sh -xe として実行されてしまうようだ。
普通であれば、スクリプトの途中であってもエラーが出れば即ビルド失敗となるので助かる仕様だろう。
しかし今回は、ビルドの過程で以下のようなことをやりたかった。

nc -z 0.0.0.0 80
if [ $? -ne 0 ]; then
  docker-compose down
  exit 1
else
  ...
fi

dockerで起動させたwebアプリケーションを、seleniumで自動テストしたい。そこで正常に起動したかどうかを判定するために、 nc -z 0.0.0.0:8000 を叩く。通じなければdockerコンテナを停止させて終了する、という流れだ。
しかしJenkinsでは #!/bin/sh -xe として実行されるので、ncコマンドが失敗した時点で即終了となる。else句の中にも入らないのでdockerも立ち上がりっぱなしだ。
dockerを落とすのを忘れたくなかったので、なんとか回避する方法がないか調べてみた。

#!/bin/sh をつけてみる

軽く調べて出てきたのがこれ。Jenkins内のシェルスクリプトの冒頭に #!/bin/sh をつけ、設定を上書きするというもの。
しかしこれでは解消しなかった。今回はwebアプリケーションがpython環境だったため、プラグインとしてshiningpandaを使っており、ビルド手順の項目でもshiningpandaの下でシェルスクリプトを実行するようにしていた。
コードを確認したわけではないが、shiningpandaの仕様として常に-xeがつけられてしまう可能性もある。

シェルスクリプトでexit codeを受け渡す

そこでさらに調べた結果、シェルスクリプトの書き方で対応することができた。

exc=0
nc -z 0.0.0.0 80 || exc=1
if [ $exc -ne 0 ]; then
  docker-compose down
  exit 1
else
  ...
fi

|| は、前の処理の結果が偽だった場合のみ、後ろの処理を行うというもの。このため、ncコマンドが失敗した場合、 ||によってexc変数に1が入る。これをつけたことで、 ncコマンドの成否に関わらず nc -z 0.0.0.0 80 || exc=1 の行は最終的に処理され、次の行に進むことができる。 そしてif句でexc変数の値を判定し、dockerを落とすことができる。

シェルスクリプトの経験値が浅いのでこれは考えつかなかったが、 || でつなぐのはいろいろなシーンで使えそうだ。