sudo -u はデフォルトで環境変数をリセットする
sudo -u user commandで別ユーザーとしてコマンドを実行すると、呼び出し元シェルの環境変数は引き継がれない。これはsudoersのenv_resetオプションがデフォルトで有効になっているためである。
Ubuntu 24.04での実行例を示す。
$ export MY_VAR=hello
$ sudo -u appuser env
HOSTNAME=272dde71e9eb
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
MAIL=/var/mail/appuser
LOGNAME=appuser
USER=appuser
HOME=/home/appuser
SHELL=/bin/sh
TERM=unknown
SUDO_COMMAND=/usr/bin/env
SUDO_USER=root
SUDO_UID=0
SUDO_GID=0
LANG=C.UTF-8
MY_VARが出力に含まれておらず、PATHやHOMEも切り替え先ユーザーであるappuserの値に置き換わっている。デプロイ用ユーザーへの切り替え時などに、呼び出し元で設定したAWS_PROFILEのような環境変数を引き継ぎたい場合、この挙動が問題になる。
-E オプションで環境変数を引き継ぐ
-Eオプション(長いオプション名は--preserve-env)を指定すると、呼び出し元の環境変数を引き継いだままユーザーを切り替えられる。
$ export MY_VAR=hello
$ sudo -E -u appuser env | grep MY_VAR
MY_VAR=hello
MY_VARがappuserのコマンド実行環境にも引き継がれている。
–preserve-env=VAR で特定の変数だけ引き継ぐ
すべての環境変数を引き継ぐのではなく、特定の変数だけ引き継ぎたい場合は--preserve-env=VAR1,VAR2のようにカンマ区切りで変数名を指定する。
$ export MY_VAR=hello
$ export ANOTHER_VAR=world
$ sudo --preserve-env=MY_VAR -u appuser env | grep -E "MY_VAR|ANOTHER_VAR"
MY_VAR=hello
指定したMY_VARのみ引き継がれ、指定していないANOTHER_VARは引き継がれない。
env_keep で常に引き継ぐ変数を設定する
-Eや--preserve-envはコマンド実行の都度指定する必要がある。特定の変数を常に引き継ぎたい場合は、/etc/sudoersにenv_keepの設定を追加する。
Defaults env_keep += "MY_VAR"
設定後は-Eを指定しなくてもMY_VARが引き継がれる。
$ export MY_VAR=hello
$ sudo -u appuser env | grep MY_VAR
MY_VAR=hello
visudoで/etc/sudoersを編集すれば、構文エラーの検査も同時に行われる。
具体例
AWS CLIのプロファイルを指定するAWS_PROFILEを、アプリケーション実行ユーザーへの切り替え時にも引き継ぐ例を示す。
$ export AWS_PROFILE=deploy
$ sudo -E -u appuser aws sts get-caller-identity
-Eを付けずに実行するとAWS_PROFILEが引き継がれず、意図しないプロファイル(デフォルトプロファイルなど)でAWS CLIが実行されてしまう。
