結論:目的別コマンド早見表
ユーザー切り替え時に環境変数を保持する手段は、大きく3パターンあります。まず手元で試すならこちらを参照してください。
# 環境変数を保持して root に切り替える(su の -m オプション)
su -m
# 環境変数を保持して特定ユーザーに切り替える
su -m deploy
# sudo で特定コマンドを実行しつつ環境変数を引き継ぐ
sudo -E make install
# sudo で環境変数付きのシェルを開く
sudo -s
# 特定の変数だけ指定して sudo に渡す
sudo --preserve-env=HTTP_PROXY,HTTPS_PROXY,NO_PROXY apt-get install curl
なぜユーザー切り替えで環境変数が消えるのか
通常の su - や sudo -i は、切り替え先ユーザーの「ログインシェル」を新たに起動します。これは /etc/profile や ~/.bash_profile を読み込んで環境を初期化するため、呼び出し元の環境変数(PATH、HTTP_PROXY、カスタム変数など)はすべてリセットされます。
ある運用現場では、Python仮想環境の PATH を設定して作業していたところ、sudo -i で root に切り替えた瞬間に仮想環境が無効になり、手順書通りに動かなくなったという事例がありました。こうした問題を回避するのが、今回紹介する環境変数の「引き継ぎ」オプションです。
su コマンドで環境変数を保持する
su には -m(または同義の -p)オプションがあり、現在のシェルの環境変数を保持したまま別ユーザーに切り替えられます。
# 環境変数を保持して root に切り替える
su -m
# 環境変数を保持して特定ユーザーに切り替える
su -m deploy
# 切り替え後、環境変数が引き継がれているか確認する
echo $HTTP_PROXY
echo $PATH
オプションなしの su は環境変数を一部引き継ぎますが、初期化ファイルの読み込みタイミングによって挙動がディストリビューションごとに異なります。-m を明示することで、「呼び出し元の環境をそのまま引き継ぐ」動作が一貫して保証されます。
なお、$SHELL と $USER/$LOGNAME は切り替え先ユーザーに合わせて更新されます。これはセキュリティ上の仕様であり、意図的な動作です。
sudo で環境変数を引き継いで権限昇格する
sudoers に env_reset(デフォルトで有効)が設定されている環境では、sudo は実行時に環境変数をリセットします。これを一時的に回避するには -E オプションを使います。
# 現在の環境変数を保持して特定コマンドを root 権限で実行する
sudo -E make install
# 環境変数を保持した root シェルを開く
sudo -s
# 特定の変数だけを指定して保持する(変数名はカンマ区切り)
sudo --preserve-env=HTTP_PROXY,HTTPS_PROXY,NO_PROXY apt-get install curl
sudo -E を使うには、sudoers に SETENV が許可されているか、管理者が !env_reset を設定している必要があります。権限がない場合は次のエラーが出ます。
sudo: you are not permitted to use the -E option
このエラーが出た場合は sudo -s を試すか、後述の sudoers 設定変更を管理者に依頼してください。
sudoers で保持する変数を恒久設定する
プロキシ環境など、特定の変数を常に引き継がせたい場合は visudo で sudoers に env_keep を追記する方法が安全かつ確実です。毎回 -E を付け忘れるリスクもなくなるため、チーム運用に向いています。
# visudo を開く(sudoers は直接編集せず必ず visudo を経由する)
sudo visudo
# Defaults セクションに以下を追記する
Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY"
Defaults env_keep += "VIRTUAL_ENV"
env_keep に PATH を追加したい場合は注意が必要です。攻撃者が PATH を書き換えて悪意のあるコマンドを実行させる「PATHインジェクション」の経路になる可能性があります。信頼できるユーザーに限定した設定にとどめてください。
よくある落とし穴と確認コマンド
環境変数を引き継いだつもりでも、切り替え後に command not found が出るケースがあります。主な原因は secure_path による PATH の上書きです。
# secure_path が設定されているか確認する
sudo -V 2>&1 | grep "Value of secure_path"
# 切り替え後の環境変数一覧を確認する
env | grep -E "PATH|PROXY|VIRTUAL"
# sudo 経由で環境変数が渡っているか確認する
sudo env | grep HTTP_PROXY
# sudo -E を通しても PATH が正しいか確認する
sudo -E which python3
secure_path が sudoers に設定されている場合、-E を使っても PATH は sudoers 側の値で上書きされます。これは意図的なセキュリティ設計です。回避するには sudoers から secure_path の行をコメントアウトするか、コマンドをフルパスで指定してください。
# visudo で secure_path をコメントアウトする例
sudo visudo
# → 以下の行の先頭に # を付けてコメントアウトする
# Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
# コメントアウトせずフルパスで回避する例(より安全)
sudo -E /home/user/.venv/bin/python3 deploy.py
secure_path の削除は本番サーバーではリスクを伴います。変更前に影響範囲を確認し、変更後は sudo -V で設定が反映されていることを必ず確認してください。フルパス指定による回避のほうが、セキュリティポリシーを崩さずに済むため現場では好まれます。
「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。
ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。
>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)
※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。
