たごもりすメモ

コードとかその他の話とか。

systemdのenvfileを普通のコマンド実行時に流用する

普段はsystemd経由で実行しているコマンドをCLIから実行したい、環境変数もsystemd経由で起動するときと同様にセットしたいのでenvfile(EnvironmentFile)をそのまま使いたいんだけどなんか微妙にやりにくくないか、と思って何度か調べたことがあるんだけど、あんまりうまい方法が検索結果に出てこない。

んだけど、あれ、これ簡単じゃん。(追記: これはごく単純なケースでしか動かなかった、後段参照)

$ env $(cat myenvfile | grep -v '^#') target-command

envfileをシェルスクリプトとして実行して追加された変数をなんとかexportすれば……みたいに考えてたけどenvコマンドで一発だった。変なコメントとか入ってると厄介だけど、こんな感じでいいのでは。ということでメモ。

空白を含む値の処理

まあいいやとスルーしてたけど値が空白を含むときに上記のコマンドだと正常に動きませんね。

$ env "$(grep -v '^#' myenvfile)" target-command

こうかな。catする意味は別になかった。

空白を含む値の処理again

上の例だとぜんぜんダメだった。ファイルのほぼ全体が最初の環境変数名にセットされて終わるという悲しい結果になる。
というか色々試してるとenvコマンドが key=value ペアのparseになんか独自のルールを持っている? っぽくって、空白文字をエスケープしようと思うとぜんぜんうまくいかない。

んで同僚の@k0kubun氏とあれこれやっていたところ彼が見付けたのが set -o allexport を使うハック。それだとちょっと他への影響が出るので、サブシェル化して実行すればいい。
このときenvfileは以下のように書かれている必要がある。

VALUE_ONE=1
VALUE_TWO="value may contain spaces"

このファイルを読み込むときに set -o allexport して全てを環境変数にする。それをサブシェルの中でやって、んでコマンドを実行する。

(set -o allexport; source envfile; target-command)

できたー!