4つの言葉の関係:rootはユーザー、sudoとsuはコマンド
4つの言葉は種類が違う。rootは、Linuxに最初から存在する特別なユーザーの名前である。管理者権限は、rootが持つ「システムのほぼすべてを操作できる権限」を指す。Linuxでは「root権限」とほぼ同じ意味で使われる。suとsudoは、一般ユーザーがこの権限を使うためのコマンドである。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グループに属するユーザーが、すべてのコマンドを実行できる。
| 項目 | su | sudo |
|---|---|---|
| 入力するパスワード | 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 -lやsu --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の原因になる。