envsubstを使ってテキストファイルをテンプレートエンジンとして使う

Bash,Docker,Kubernetes

はじめに

Kubernetesのマニフェストファイル内に環境変数を埋め込み、出力内容を動的に変更したい場合があると思います。

kustomizehelm といったツールを利用することで
Kubernetesのマニフェストファイルに変数を埋め込むことはできます。
しかし、そこまで大層な仕組みを導入するような手間を掛けたくない。

sed を使う方法もありますが、可読性は低くなります。

そんな場合、 enbsubst コマンドを利用することでかんたんに実現することができます。

検証環境

$ uname -moi
x86_64 x86_64 GNU/Linux

$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

envsubst コマンドとは

envsubst コマンドを使うと,変数展開など「テンプレートエンジン」のような仕組みを実現できます。

準備

僕の環境(CentOS)には最初にインストールされていなかったため、まずはインストールから行いました。

$ yum install -y gettext

$ which envsubst
/usr/bin/envsubst

Mac環境の場合は Homebrew でインストールできると思います。(僕のMacには気がついたらインストールされていました。)
apt でもきっと用意にインストールできるでしょう。

バージョンを確認します。

$ envsubst --version
envsubst (GNU gettext-runtime) 0.19.8.1
Copyright (C) 2003-2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Bruno Haible.

envsubst コマンドでテキストファイルに変数を埋め込んで見る

早速使ってみましょう。

変数を埋め込んだテキストを用意します。

$ cat <<'EOF' >template.txt
${GREETING}, ${YOUR_NAME}!
${YOUR_NAME}'s HOME is ${HOME}.
EOF

# 内容を確認
$ cat template.txt
${GREETING}, ${YOUR_NAME}!
${YOUR_NAME}'s HOME is ${HOME}.

ここでは3つの変数をテキストファイル内に記載しています。

  • GREETING
  • YOUR_NAME
  • HOME

HOME は、ログインシェルで接続しているユーザのホームディレクトリを表す環境変数ですね。

# 僕は /root ユーザで今回の操作を行っています。
$ echo $HOME
/root

テキストファイルに対して変数を埋め込むには、 envsubst に対してファイルの内容をリダイレクトさせます。

$ envsubst < template.txt
, !
's HOME is /root.

なんとも悲しい結果になってしまいました。
${GREETING}${YOUR_NAME} の2つの記述が消えてしまいました。
${HOME} の記述は /root に置き換えられていますね

原因は GREETINGYOUR_NAME の2つの変数を定義していなかったためです。

改めて変数を定義して再実行してみましょう。ただし、変数は export する必要があることに注意してください。

$ export GREETING=Hello
$ export YOUR_NAME=genzouw

$ envsubst < template.txt
Hello, genzouw!
genzouw's HOME is /root.

変数の値を変更すれば正しく反映されます。

$ export GREETING=こんにちわ
$ export YOUR_NAME=root

こんにちわ, root!
root's HOME is /root.

${...} 形式で記述しているけど変数として展開してほしくない場合

もう一度先程のテンプレートファイルを見てみます。

$ cat template.txt
${GREETING}, ${YOUR_NAME}!
${YOUR_NAME}'s HOME is ${HOME}.

ここで、 ${GREETING}${YOUR_NAME} の部分ですが、変数を定義しておかないと envsubst 適用後に空白になってしまいます。
${GREETING}${YOUR_NAME} を「変数として展開してほしくない」という場合は、
変数として展開してほしい HOME だけを envsubst コマンドの引数に指定します。

$ envsubst '${HOME}' < template.txt
${GREETING}, ${YOUR_NAME}!
${YOUR_NAME}'s HOME is /root.

引数はシングルクォーテーションで囲んで $XXX とする点に注意です。
GREETING も対象にする場合は以下のように指定します。

$ export GREETING=hello

$ envsubst '${HOME} ${GREETING}' < template.txt
hello, ${YOUR_NAME}!
${YOUR_NAME}'s HOME is /root.

ひとこと

便利そうですが、 ${...} または $... の記述がテキストファイル内に存在すると変数展開されてしまいます。
Nginxの設定ファイルや.htaccessのようなファイルには $ の記述がよく使われますし、気をつけないと意図しない変換が行われる点に注意が必要です。