monolithic kernel

chezmoi でのスクリプトキャッシュをクリーンな環境で作る

過去に、chezmoi のテンプレート機能を使ってシェルの起動を高速化する方法を紹介した。

基本的にはこれでうまくいくのだが、コマンドによっては問題になる場合がある。呼び出し時の環境変数の内容を考慮して初期化処理を変えるような場合である。mise なんかがそれに該当する。

普段使っている環境で chezmoi コマンドを実行すると、その時の環境変数で chezmoi コマンドが実行され、そこから起動されるプロセスにも引き継がれる。それによって、期待したスクリプトのキャッシュが生成されない場合がある。

これを回避するためには、呼び出し元の環境変数の影響を排除して chezmoi コマンドやそこから呼び出されるコマンドを実行できればよい。そのために、環境変数をリセットして chezmoi コマンドを実行するようなラッパーを作成した。

#!/bin/bash
# Run chezmoi in a clean environment with Homebrew environment variables set up.
set -eu
exec env -i \
HOME="$HOME" \
HOMEBREW_PREFIX="${HOMEBREW_PREFIX:-/opt/homebrew}" \
GITHUB_ACTIONS="${GITHUB_ACTIONS:-}" \
/bin/bash --noprofile --norc -s "$@" << 'EOF'
eval "$(/usr/libexec/path_helper -s)"
eval "$("$HOMEBREW_PREFIX/bin/brew" shellenv)"
exec chezmoi "$@"
EOF

env コマンドの -i オプションを指定することで、継承した環境変数を無視してコマンドを実行できる。そこから起動する bash コマンドにも --noprofile --norc オプションを付けて設定の読み込みを抑止している。それだけだと必要な環境変数も消えてしまうので、最低限必要になる HOME/usr/libexec/path_helper の結果 (macOS の場合) や、Homebrew でインストールしたコマンドを使うための brew shellenv の結果も設定したうえで chezmoi コマンドを実行している。

zsh-smartcache とかのほうが本来の実行タイミングでキャッシュを作るので問題が少ないのかなと思いつつ、一旦これでもできてますということで。chezmoi コマンドの中でやるのにふさわしい複雑な操作がでてきたら価値が出てくるかもしれない。


Related articles