sudo -u はデフォルトで環境変数をリセットする

sudo -u user commandで別ユーザーとしてコマンドを実行すると、呼び出し元シェルの環境変数は引き継がれない。これはsudoersenv_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が出力に含まれておらず、PATHHOMEも切り替え先ユーザーであるappuserの値に置き換わっている。デプロイ用ユーザーへの切り替え時などに、呼び出し元で設定したAWS_PROFILEのような環境変数を引き継ぎたい場合、この挙動が問題になる。

-E オプションで環境変数を引き継ぐ

-Eオプション(長いオプション名は--preserve-env)を指定すると、呼び出し元の環境変数を引き継いだままユーザーを切り替えられる。

$ export MY_VAR=hello
$ sudo -E -u appuser env | grep MY_VAR
MY_VAR=hello

MY_VARappuserのコマンド実行環境にも引き継がれている。

–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/sudoersenv_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が実行されてしまう。

参考