Memo:

アイデアや気づきとかが雑に書き殴られる

失敗した場合に安全に処理を中断するためのbash内での環境変数export方法(ShellCheck に教えてもらう)

例えば以下のようなスクリプトがあって、その結果を bash 内で実行し標準出力を環境変数として export したい。しかも、そのスクリプトは失敗する可能性があると仮定する(インターネット接続が必要なのに繋がってない環境で実行された。設定ミスによって権限が足りてない。単純なバグ...など)。

これがビルドやデプロイのために実行されるコードだった場合(例えば Docker の entrypoint )、実行に失敗した瞬間に安全のため処理を中断させたい。必要な環境変数を設定し損ねたアプリケーションは正常に動くとは全く期待できないし、想定してない動作をする恐れもあるため。

import sys

# 検証のため何か引数が渡された場合、エラーにする
raise_error = bool(len(sys.argv) >= 2 and sys.argv[1])
if raise_error:
    raise Exception("Cannot get the token.") 

print("secret-token-string")

中断させる書き方

set -e と書くことで、実行したコマンドでエラーが出た時に中断させることができる。

export は一行で export SECRET_TOKEN="$(python ./get_token.py)" と書くこともできるが、このように書いてしまうと python ./get_token.py が失敗しても「export コマンド」は成功する。よって最終的なコマンドの実行ステータスは 0 となり中断されない。

export コマンドを分けることによって、ちゃんとコマンドの失敗時に処理が中断されるようになる。

#!/bin/bash

set -e

SECRET_TOKEN="$(python ./get_token.py error)"
export SECRET_TOKEN

echo "\$SECRET_TOKEN = '$SECRET_TOKEN'"
Traceback (most recent call last):
  File "./get_token.py", line 6, in <module>
    raise Exception("Cannot get the token.") 
Exception: Cannot get the token.

export を一行で書いた場合

一番最後の echo コマンドが実行された。環境変数に空文字が設定された状態になってしまった。

#!/bin/bash

set -e

export SECRET_TOKEN="$(python ./get_token.py error)"
 
echo "\$SECRET_TOKEN = '$SECRET_TOKEN'"
Traceback (most recent call last):
  File "./get_token.py", line 6, in <module>
    raise Exception("Cannot get the token.") 
Exception: Cannot get the token.
$SECRET_TOKEN = ''

ShellCheck でまずい書き方を教えてもらう

export の書き方は ShellCheck の wiki で知ることができた。

ShellCheck: SC2155 – Declare and assign separately to avoid masking return values.

ShellCheck は shell script 用の静的な解析ツール(linter)で、VS Code の extension として使えたり、CI に組み込むことができる(公式の docker image があるので CI 化は楽にできた)。

個人的に、shell script に関してはわからないことだらけなので積極的に使っていきたい。

github.com