ユニファ開発者ブログ

ユニファ株式会社システム開発部メンバーによるブログです。

sudo実行時のカレントディレクトリや環境変数などの挙動について

おはこんにちばんわ! ひさびさなユニファのインフラのすずきです。

最近八王子から、都心に引っ越してきました。
やはり通勤時間が短いと快適ですよね。
そして先日AWSのRe:Inventのチケット申込みが始まりましたね。
今年は行きたい…い゛ぎたい!!!!

と前置きはおいて今回は2度めのsudo関連のブログです。

前回のsudoの記事はこちら、

tech.unifa-e.com

なんかそこそこ見てもらえてるみたいで、関連記事かけという強いプレッシャーの元今回書くことにしました。

では本題

みなさんつかってるsudo、実行方法(optionなど)やsudersの設定で環境変数の持ち方がかわっているのご存知でしょうか?
exportしている内容が反映されていたりいなかったり、sudoユーザのローカル変数が適用されていたりいなかったり、etc...

そういった違いの事例をいくつか紹介しようと思います。

pwdで実験

みなさん pwd 使いますよね、ね?

それをつかってAmazon Linux上で動作を見てみます。

普通にpwd

[ec2-user@ip-10-255-0-57 ~]$ pwd
/home/ec2-user

ec2-userのホームですね。

sudoでpwd

[ec2-user@ip-10-255-0-57 ~]$ sudo pwd
/home/ec2-user

ec2-userのホームですね。

試しに別のユーザを作って実施

[ec2-user@ip-10-255-0-57 ~]$ sudo adduser test
[ec2-user@ip-10-255-0-57 ~]$ sudo -u test  pwd
/home/ec2-user

sudo ではカレントディレクトリの場所を移動しないから

でも変更したい!

ホームディレクトリ変えたい、変更ユーザのホームディレクトリに必要なスクリプトがあるんだと言う場合

-i オプションをつかってみる

[ec2-user@ip-10-255-0-57 ~]$ pwd
/home/ec2-user
[ec2-user@ip-10-255-0-57 ~]$ sudo -i pwd
/root
[ec2-user@ip-10-255-0-57 ~]$ sudo -u test -i pwd
/home/test

変わりました、-i はログインしなおすというか、ログインシェルを実行しつつコマンドを実行するものになっています。
ログインシェルを叩き直すということは、~/.bashrc などを読み込んでくれるので環境変数の効き方がかわってきますね。

環境変数の上書き

前準備として、/root/.bashrcexport TEST=bashrc を追記しておきます。

[ec2-user@ip-10-255-0-57 ~]$ sudo -i bash -c "echo 'export TEST=bashrc' >> ~/.bashrc"

また、現在のカレントシェルに同じ名前の環境変数設定しておきます。

[ec2-user@ip-10-255-0-57 ~]$ export TEST=prompt

ログインシェル実行での環境変数の上書き

通常

[ec2-user@ip-10-255-0-57 ~]$ env |grep TEST
TEST=prompt

先程設定したものがみえる

sudo

[ec2-user@ip-10-255-0-57 ~]$ sudo env |grep TEST

値なし

sudo 別ユーザ

[ec2-user@ip-10-255-0-57 ~]$ sudo -u test env |grep TEST

値なし

sudo すると環境変数がリセットされてしまうので見れないですね…
-i をつかってみます

sudo

[ec2-user@ip-10-255-0-57 ~]$ sudo -i env |grep TEST
TEST=bashrc

お、今までとはちがうbashrcが返ってきました。
これは-iオプションでrootのログインシェルを実行しているため。
/root/.bashrc に設定した環境変数が読まれています。

sudo 別ユーザ

[ec2-user@ip-10-255-0-57 ~]$ sudo -i -u test env |grep TEST

これはログインシェルに環境変数を設定していないので返ってこないですね。

環境変数を引き継ぐオプションの利用

逆にカレントシェルに設定した環境変数をsudo先で使いたいんじゃーって場合です。
-E 初登場のこのオプションを使います。
今までのと比較しながらつかってみます。

通常

[ec2-user@ip-10-255-0-57 ~]$ env |grep TEST
TEST=prompt

はい

sudo

[ec2-user@ip-10-255-0-57 ~]$ sudo  env |grep TEST
[ec2-user@ip-10-255-0-57 ~]$ sudo -i env |grep TEST
TEST=bashrc
[ec2-user@ip-10-255-0-57 ~]$ sudo -i -E env |grep TEST
TEST=bashrc
[ec2-user@ip-10-255-0-57 ~]$ sudo -E env |grep TEST
TEST=prompt

-i のときはログインシェルを実行してしまうので、bashrcで上書きされてしまっていますね。
-Eのみのときは、カレントシェルに設定したものが返ってくるようになりました。

sudo 別ユーザ

[ec2-user@ip-10-255-0-57 ~]$ sudo -u test env |grep TEST
[ec2-user@ip-10-255-0-57 ~]$ sudo -u test -i env |grep TEST
[ec2-user@ip-10-255-0-57 ~]$ sudo -u test -i -E env |grep TEST
[ec2-user@ip-10-255-0-57 ~]$ sudo -u test -E env |grep TEST
TEST=prompt

別ユーザの場合はbashrcも設定されてないので -E をつけたときのみ返ってきます。

簡単になりますが以上でsudo実行時のカレントディレクトリや、環境変数の話になります。

最近サーバレスやコンテナなどでsudo駆使するみたいなことはあまりないかもしれませんが、sudoを駆使したスクリプトの実行が必要で、思うように環境変数が入らない、思った挙動じゃない方などの助けになれば幸いです。

淡い記憶で書いているのでそもそも間違えてるんだぜみたいなお小言あればどしどしいただけたらと思います。

すずき