sudo -i と sudo su -の違い

どちらもrootユーザーに昇格することができるがこれらの違いが気になったので調査結果をメモ。

まず、これらのコマンドがどういう意味であるかを調べた。

  • sudo: Super User DO
  • su: Substitute User

sudo -iオプションの意味は simulate initial loginであるようだ。

違い1: 実行されるプロセス数が違う

当然だが、sudo su -sudosuコマンドを実行する。rootに昇格している間はこれらのプロセスが立ち上がったままとなる。 対してsudo -iコマンドはsudoコマンドのみを実行する。rootに昇格している間はsudoプロセスのみとなる。

どちらも利用したことがあればわかるが、体感的な速度差はない。

リソースは以下のような結果となった。

sudo su -昇格時

# pidstat -r -C su
Linux 5.4.0-58-generic (ubuntu2004)     2020年12月21日  _x86_64_        (1 CPU)

15時26分13秒   UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
15時26分13秒     0      5064      0.00      0.00   10280    4572   0.49  sudo
15時26分13秒     0      5065      0.00      0.00    9428    4292   0.46  su
$ time sudo su - -c :

real    0m0.013s
user    0m0.008s
sys     0m0.003s

sudo -i昇格時

~# pidstat -r -C su
Linux 5.4.0-58-generic (ubuntu2004)     2020年12月21日  _x86_64_        (1 CPU)

15時31分08秒   UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
15時31分08秒     0      6061      0.00      0.00   10364    4572   0.49  sudo
$ time sudo -i :

real    0m0.009s
user    0m0.006s
sys     0m0.003s

リソース面だけでみれば、sudoコマンドの結果はほぼ変わらず、suコマンドが加わった分、sudo -iほうが有利なようだ。

違い2: 環境変数

sudo -iの場合以下の環境変数がセットされている。

  • SUDO_COMMAND: 実行コマンド
  • SUDO_UID: 昇格前のUID
  • SUDO_GID: 昇格前のGID
  • SUDO_USER: 昇格前のUSER

CentOSの sudo -iだと/usr/local/binがPATH環境変数がセットされていない。

CentOS7, CentOS8で動作を確認

$ sudo -i echo '$PATH'
/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/root/.dotnet/tools:/root/bin

$ sudo su - -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/.dotnet/tools:/root/bin

Ubuntu20.04ではPATH環境変数に /usr/local/binがセットされていることを確認。

これは/etc/sudoersのデフォルト設定による違いとなる。

CentOS8

$ sudo grep secure_path /etc/sudoers
Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin

Ubuntu20.04

$ sudo grep secure_path /etc/sudoers
Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"

suコマンドでPATH環境変数は suコマンドがデフォルトでセットしているようだ。

       ENV_SUPATH (string)
           Defines the PATH environment variable for root.  The default value is /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin.

環境変数の引継ぎ

sudo -iでは環境変数が引き継がれる

$ sudo -i date
2020年 12月 21日 月曜日 19:37:30 JST

$ LANG=C sudo -i date
Mon Dec 21 19:37:36 JST 2020

sudo su -では環境変数が引き継がれない

$ sudo su - -c date
2020年 12月 21日 月曜日 19:38:54 JST

$ LANG=C sudo su - -c date
2020年 12月 21日 月曜日 19:39:44 JST

昇格後に環境変数をセットすれば対応可能

$ sudo su - -c 'LANG=C date'
Mon Dec 21 19:40:06 JST 2020

これは一長一短だと思う。個人的には引き継ないsudo su -のほうが自然な動作に感じる。

まとめ

違い sudo -i sudo su -
プロセス sudo のみ実行 sudo, suを実行
デフォルト環境変数 /etc/sudoersのsecure_path
(ディストリビューションによってデフォルト値が異なる)
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
環境変数の引継ぎ 引き継ぐ 引き継がない

各種リソース面では sudo -iが有利、環境変数関連は sudo su -のほうが好み(ディストリビューションの違いを意識しなくてよい)

用途によって使い分けるとよさそう。

参考情報

The Differences between Su, Sudo Su, Sudo -s and Sudo -i

linux - What is the difference between sudo -i and sudo su - - Server Fault

command line - 'sudo su -' vs 'sudo -i' vs 'sudo /bin/bash' - when does it matter which is used, or does it matter at all? - Ask Ubuntu

bash 管理者実行「su」「su -」「sudo -s」を比べてみる(スド、スドゥ) - min117の日記

suとsudoの違い - Qiita