4つの言葉の関係:rootはユーザー、sudoとsuはコマンド

4つの言葉は種類が違う。rootは、Linuxに最初から存在する特別なユーザーの名前である。管理者権限は、rootが持つ「システムのほぼすべてを操作できる権限」を指す。Linuxでは「root権限」とほぼ同じ意味で使われる。susudoは、一般ユーザーがこの権限を使うためのコマンドである。rootと管理者権限は「誰が何を持っているか」の話で、suとsudoは「その権限をどうやって使うか」の話になる。

rootの正体はUID 0のユーザー

Linuxはユーザーを名前ではなく、UID(ユーザーID)という番号で区別する。rootのUIDは0である。カーネルはUID 0のプロセスについて、ファイルのアクセス権チェックをほとんど省略する。他人のファイルの読み書き、システム設定の変更、ソフトウェアのインストールがrootにできるのはこのためだ。自分が今どのユーザーで動いているかはidコマンドで確認できる。

$ id
uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo)
$ sudo id
uid=0(root) gid=0(root) groups=0(root)

rootは強力なぶん、打ち間違い一つでシステムを壊せてしまう。そのため普段は一般ユーザーで作業し、必要なときだけ権限を借りるのが基本になる。権限の借り方がsuとsudoである。

sudoとsuの違いは「誰のパスワードで、どの範囲を借りるか」

su(switch user)は、別のユーザーに切り替えるコマンドである。ユーザー名を省略するとrootに切り替わる。このとき入力するのは、切り替え先であるrootのパスワードだ。切り替えた後は、exitするまでそのシェルで打つすべてのコマンドがrootとして実行される。

sudoは、指定したコマンドを1回だけ別のユーザー(既定ではroot)として実行する。入力するのは自分のパスワードである。誰がどのコマンドを実行してよいかは、/etc/sudoersという設定ファイルで決まる。多くの環境の初期設定では、Debian/Ubuntu系はsudoグループ、Fedora/RHEL系はwheelグループに属するユーザーが、すべてのコマンドを実行できる。

項目susudo
入力するパスワードrootのパスワード自分のパスワード
権限が及ぶ範囲exitするまでの全操作指定した1コマンド
使える人rootのパスワードを知っている人sudoersで許可された人
記録切り替えたことが記録される実行したコマンドごとに記録される

複数人で管理するサーバーでは、sudoのほうが扱いやすい。rootのパスワードを共有する必要がなく、誰がどのコマンドを実行したかがログに残るからだ。ログの保存先はディストリビューションによって異なり、Debian系では/var/log/auth.log、RHEL系では/var/log/secure、またはsystemdのジャーナルに記録される。

Ubuntuでは、インストール時の既定でrootのパスワードが設定されていない。このためsuを実行しても認証に失敗する。これは故障ではなく、sudoだけを使う前提の設計である。自分がsudoで何を実行できるかはsudo -lで確認できる。

su と su - の違いはログイン環境を読み込むかどうか

su -(su -lsu --loginとも書く)は、rootとしてログインし直したのと同じ状態にする。rootのシェル設定ファイルが読み込まれ、カレントディレクトリはrootのホーム(通常は/root)に移る。PATHなどの環境変数もrootの設定に整えられる。ハイフンなしのsuが切り替えるのはユーザーだけで、カレントディレクトリや多くの環境変数は元のユーザーのものが残る。

$ cd ~/project
$ su
Password:
# pwd
/home/alice/project
# exit
$ su -
Password:
# pwd
/root

環境が混ざると特に困るのが、コマンドを探す場所を決めるPATHである。ディストリビューションによっては、一般ユーザーのPATHに/usr/sbinなどの管理用ディレクトリが含まれない。この状態でsuだけを使うと、rootになったのに管理コマンドが「command not found」になることがある。逆に、一般ユーザーが自分用に置いた同じ名前のプログラムが、rootとして実行されてしまう危険もある。特別な理由がない限りsu -を使う。sudoで同じことをするなら、sudo -iがrootのログインシェルを起動する。

sudoで作ったファイルの所有者はrootになる

sudoで実行したコマンドはrootとして動く。そのため、そのコマンドが作ったファイルやディレクトリの所有者もrootになる。

$ sudo mkdir ~/tools
$ ls -ld ~/tools
drwxr-xr-x 2 root root 4096 ... /home/alice/tools
$ touch ~/tools/memo.txt
touch: cannot touch '/home/alice/tools/memo.txt': Permission denied

自分のホームディレクトリの中なのに書き込めない、という状況はこうして生まれる。sudo git cloneで取得したリポジトリで、後からgit pullが失敗するのも同じ原因だ。直すにはchownで所有者を自分に戻す。

$ sudo chown -R $USER: ~/tools

-Rは、中のファイルも含めてまとめて変更する指定である。$USER:のようにユーザー名の後ろにコロンを付けると、グループもそのユーザーのログイングループに変わる。そもそもホームディレクトリ内の作業にsudoが必要な場面は少ない。Permission deniedが出たら、sudoを付ける前に、そこが本当に管理者権限の必要な場所かを確かめる。

sudo echo > ファイル がPermission deniedになる理由

設定ファイルに1行書き込もうとして、次のように失敗することがある。

$ sudo echo 'Welcome' > /etc/motd
bash: /etc/motd: Permission denied

原因は、>によるリダイレクト(出力先をファイルに切り替える機能)を処理するのが、sudoではなく今使っているシェルだという点にある。シェルはコマンドを実行する前に、一般ユーザーの権限で/etc/motdを書き込み用に開こうとする。この時点で失敗するため、sudoは実行すらされない。仮に実行されても、sudoの権限が及ぶのはecho 'Welcome'の部分だけである。

解決するには、ファイルへの書き込みそのものをrootで行う。定番はteeコマンドを使う方法だ。teeは標準入力から受け取った内容をファイルに書き込む。

$ echo 'Welcome' | sudo tee /etc/motd > /dev/null
$ echo 'Welcome' | sudo tee -a /etc/motd > /dev/null

1行目はファイルを上書きし、-aを付けた2行目は末尾に追記する。teeは書き込んだ内容を画面にも表示するので、不要なら> /dev/nullで捨てる。この>の書き込み先は誰でも書き込める/dev/nullなので、一般ユーザーのシェルが処理しても問題ない。シェルごとrootで動かすsudo sh -c 'echo Welcome > /etc/motd'という書き方もある。ただし、引用符が入れ子になりやすく、間違いの元になる。

既存の設定ファイルを編集するならsudoedit /etc/motd(sudo -eと同じ)が使える。sudoeditはファイルのコピーを自分の権限でエディタに開かせ、保存後にrootとして元の場所へ書き戻す。エディタそのものをrootで動かさずに済むのが利点である。

どれを使うかの判断基準

日常の管理作業では、必要なコマンドにだけsudoを付ける。管理コマンドを続けて何十も打つ場合に限り、sudo -iまたはsu -でrootのシェルに入る。作業が終わったらすぐにexitする。ハイフンなしのsuは、元の環境を引き継ぐ明確な理由があるときだけ使う。

Permission deniedが出たら、まずls -lでファイルの所有者を、idで今のユーザーを確認する。所有者が意図せずrootになっていればchownで戻す。リダイレクトで失敗しているならteeを使う形に書き換える。「sudoを付ければ動く」という理由だけでsudoを足すと、root所有のファイルが増え、次のPermission deniedの原因になる。