はじめに (対象読者・この記事でわかること)

この記事は、Linux サーバを触る機会のあるエンジニア初学者〜中級者を対象にしています。
「とりあえず sudo su root で権限を上げて作業してるけど、何が起きてるか実はよくわかってない……」という方に読んでいただきたい内容です。

この記事を読むことで、以下のことがわかります。

  • sudo su root が内部的にどのような処理を経て root シェルを起動しているか
  • なぜ「root で全部やる」のではなく sudo を使うべきなのか
  • セキュアでトラブルの少ない権限管理のベストプラクティス

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。 - Linux の基本的なコマンド操作(ls, cd, cat など) - ファイルパーミションと所有権の基礎知識 - エディタ(vim や nano)での簡単なファイル編集

sudo su root の仕組み:認可・認証からシェル起動まで

「sudo」は「Superuser Do」、「su」は「Substitute User」の略です。
sudo su root と打つと、以下の流れで root 権限のシェルが起動します。

  1. sudo が /etc/sudoers を読み込み、「自分は root としてコマンドを実行してよいか」を検証
  2. 認証が必要な場合はパスワードを要求(デフォルトでは 5 分間キャッシュ)
  3. sudo が su root を root 権限で実行
  4. su が /bin/sh(または /etc/passwd で指定されたシェル)を root として起動
  5. 結果、対話的な root シェルが手に入る

つまり「sudo で su を呼び出し、su が root シェルを起動する」という二段構えです。
近年のディストリビューションでは sudo -isudo -s が推奨されますが、古い書籍やレガシーなスクリプトでは今でも sudo su - を見かけます。

具体的な挙動とログの読み方

ステップ1:sudoers の検証

/etc/sudoers または /etc/sudoers.d/* に以下のように書かれている前提で実験してみます。

# /etc/sudoers.d/kousukei
kousukei ALL=(ALL:ALL) ALL

この行は「kousukei ユーザは、任意のホストで、任意のユーザ・グループとして、任意のコマンドを実行してよい」という意味です。
sudo -l で実際に許可されているコマンドが一覧表示できます。

Bash
$ sudo -l User kousukei may run the following commands: (ALL : ALL) ALL

ステップ2:実際に sudo su root を実行してみる

ターミナルで sudo su root を実行し、別の端末から journalctl -f でログを追いかけてみます。

Bash
# 端末1 $ sudo su root [sudo] password for kousukei: root@host:/home/kousukei#
Bash
# 端末2 $ journalctl -f Jun 03 12:34:12 host sudo[12345]: kousukei : TTY=pts/0 ; PWD=/home/kousukei ; USER=root ; COMMAND=/usr/bin/su root Jun 03 12:34:12 host su[12346]: Successful su for root by root Jun 03 12:34:12 host su[12346]: + /dev/pts/0 root:root

sudo が「誰が、どこで、どのユーザとして、どのコマンドを実行したか」を syslog に記録しています。
これにより「いつ誰が root になったか」が後から追跡できます。

ステップ3:環境変数の違いを観察する

sudo su rootsudo -i では環境変数の引き継ぎ方が異なります。

Bash
$ sudo su root # env | grep -E 'HOME|USER|SUDO' USER=root HOME=/root # echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Bash
$ sudo -i # env | grep -E 'HOME|USER|SUDO' USER=root HOME=/root SUDO_USER=kousukei # echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin

sudo -i の方が SUDO_USER が残り、パス