sudoでシェルスクリプトを実行した際にPATHが正しく引き継がれない場合の対処
はじめに
sudo コマンドを使ってシェルスクリプトを実行した際に、実行ユーザの PATH 環境変数の設定が引き継がれずに困ってしまうことがあります。
セキュリティを考慮しての仕組みですが、引き繋がれない原因と対処について解説します。
最近の sudo はデフォルトでは PATH は引き継がれません。
sudo の -E
オプションが必要です。この解決方法として Web 上でよく見かけます。
ただし、これだけで解消しない場合もあるため、今回のエントリを書こうと思いました。
検証環境
$ cat /etc/os-release | head -n 2
NAME="CentOS Linux"
VERSION="7 (Core)"
$ bash -version | head -n 1
GNU bash, version 5.0.18(1)-release (x86_64-apple-darwin19.5.0)
$ sudo --version | head -n 1
Sudo version 1.8.23
問題の事象を確認
まずは今回取り上げる事象がどんなものか具体的にコマンドを実行しながら見ていきたいと思います。
いくつか準備をした後、再現させて見たいと思います。
準備その 1: adm
ユーザの設定
事前に作成しておいた adm
ユーザ( wheel
グループに所属 )を使います。
$ id
uid=3(adm) gid=4(adm) groups=4(adm),10(wheel)
準備その 2: "sudo" の設定
次に、 sudo の設定ファイルである /etc/sudoers
は以下のような設定になっています。
# コメント行や空行を除去
$ cat /etc/sudoers | grep -v '^#' | grep -v '^$'
Defaults !visiblepw
Defaults always_set_home
Defaults match_group_by_gid
Defaults always_query_group_plugin
Defaults env_reset
Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
Defaults env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
root ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL
%wheel
グループに対してパスワード不要で sudo が利用できるようになっています。
準備その 3: "PATH" 環境変数を出力するだけのシェルスクリプトを作成
最後に、 PATH 環境変数の設定値を確認するためだけのシェルスクリプトを作成します。
test.sh
というファイル名で作成します。
cat <<'EOF' >./test.sh
#!/usr/bin/env bash
echo "${PATH}"
EOF
$ chmod 777 test.sh
"adm" ユーザで test.sh
を実行してみる
準備ができたので、 adm ユーザで test.sh
ファイルを実行してみます。
- sudo なし
- sudo あり
のそれぞれの方法で実行してみます。
# sudo なしで実行!
$ ./test.sh
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin
# sudo ありで実行!
$ sudo ./test.sh
/usr/bin:/bin:/usr/sbin:/sbin
このように sudo なしだと PATH 環境変数の設定が実行ユーザの設定とは異なる値となってしまいます。
「sudoなしだと正常に動いていたのに、 sudoありだとコマンドが見つからない!」** といった問題が発生することがあります。
原因
原因は、 /etc/sudoers
に設定されている以下の 1 行になります。
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
secure_path
が設定されていると、設定されている値で PATH は上書きされてしまいます。
/usr/local/bin
ディレクトリなどに得体のしれないファイルが配置されていた場合( ls
という名前のスクリプトで rm -rf /
するロジックが入っているなど )を考慮したセキュリティ対策なのでしょうが、邪魔な場合もあります。
対処
ここでは対処法を 3 つ紹介します。
対処法 1: secure_path
の行をコメントアウト
/etc/sudoers
の secure_path
の行をコメントアウトしてしまいます。
/etc/sudoers
を変更したあとは、もしすでに adm
ユーザでログインしていた場合は一度ログアウトしないと反映されません 。
$ sudo ./test.sh
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin
対処法 2: exempt_group
を設定 + env_keep
を設定
/etc/sudoers
に exempt_group
の行を追記します。
exempt_group
に設定されたグループに所属するユーザを一律 secure_path
の制限から免除させます。
Defaults exempt_group = wheel
また、 /etc/sudoers
に env_keep
の行を追記します。
sudo 実行時に、 env_keep
に設定されている環境変数だけが引き継がれます。
PATH を追記することで設定が引き継がれるようになります。
Defaults env_keep += "PATH"
$ sudo ./test.sh
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin
対処法 3: exempt_group
を設定 + sudo -E
対処法 2 に似ていますが、 Defaults env_keep += "PATH"
の記述は追記しません。
その代わりに、 adm
ユーザでコマンド実行する際に sudo -E
のように -E
オプションを付与します。
# 環境変数は引き継がれない
$ sudo ./test.sh
/usr/bin:/bin:/usr/sbin:/sbin
# 環境変数は引き継がれる
$ sudo -E ./test.sh
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin
ひとこと
環境によって、 secure_path
の設定がされておらず、 sudo -E
だけで PATH 引き継ぎの問題が解決したりします。sudo -E
で問題が解決しない場合の参考になれば幸いです。
ディスカッション
コメント一覧
まだ、コメントがありません