👨

sudo su とかしてる人はだいたいおっさん

2021/05/25に公開

https://twitter.com/tmtms/status/1395691473266372611

テキトーに書いたこれが「ややウケ」だった。

そういや自分が sudo 使い始めたのは20年以上前で、うろ覚えなので調べてみた。

まとめ

カレントディレクトリ 引き継がれる環境変数 シェル ログインシェル
su 変わらない ほぼすべて デフォルトのシェル No
su - ユーザーのホーム TERM のみ デフォルトのシェル Yes
sudo su 変わらない 一部 デフォルトのシェル No
sudo su - ユーザーのホーム TERM のみ デフォルトのシェル Yes
sudo -s 変わらない 一部 実行時の $SHELL No
sudo -i ユーザーのホーム 一部 デフォルトのシェル Yes

sudo susudo -s はほぼ同じ。実行されるシェルが異なることがある。

sudo su -sudo -i もほぼ同じ。環境変数のクリア的な意味だと sudo su - の方が強い。

以下は別に読まなくてもいい。

su

別のユーザーでシェルを実行するコマンド。自分は「す」とか「えすゆー」とかと呼んでる。
元は super user とか switch user とか substitute user の略だったらしい。

デフォルトでは root になるが、引数でユーザー名を指定するとそのユーザーになる。
新ユーザーのデフォルトのシェルとして設定されているシェルが実行される。

入力するパスワードは新ユーザーのパスワード。

~% su
Password: (rootのパスワード)
root@hostname:/home/tmtms# id
uid=0(root) gid=0(root) groups=0(root)
root@hostname:/home/tmtms# 
~% su hoge
Password: (hogeのパスワード)
hoge@hostname:/home/tmtms$ id
uid=1001(hoge) gid=1001(hoge) groups=1001(hoge)
hoge@hostname:/home/tmtms$ 

ユーザー名につづけて引数を追加するとシェルに渡される。

~% su hoge -c id
Password: (hogeのパスワード)
uid=1001(hoge) gid=1001(hoge) groups=1001(hoge)
~% 

カレントディレクトリは変わらない。

シェルが bash の場合は /etc/bash.bashrc~/.bashrc を実行するが、ログインシェルではないので、/etc/profile~/.profile は実行されない。

環境変数は HOME, SHELL が設定される。root 以外のユーザーになる場合は USER, LOGNAME もセットされる。それ以外の環境変数は引き継がれる。

Ubuntu で実際に su を試してみたらさらに PATH, MAIL も変更された。

PATH/etc/login.defs に次のような設定があるんだけど、値が違うんでこれではなさそう。

#
# *REQUIRED*  The default PATH settings, for superuser and normal users.
#
# (they are minimal, add the rest in the shell startup files)
ENV_SUPATH      PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV_PATH        PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

/etc/pam.d/su/etc/environment に次のように書かれてて、どうやらこれが効いてるっぽい。

# This module parses environment configuration file(s)
# and also allows you to use an extended config
# file /etc/security/pam_env.conf.
# 
# parsing /etc/environment needs "readenv=1"
session       required   pam_env.so readenv=1
# locale variables are also kept into /etc/default/locale in etch
# reading this file *in addition to /etc/environment* does not hurt
session       required   pam_env.so readenv=1 envfile=/etc/default/locale
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"

MAIL/etc/pam.d/su のこれが効いてる。たぶん。

# Defines the MAIL environment variable
# However, userdel also needs MAIL_DIR and MAIL_FILE variables
# in /etc/login.defs to make sure that removing a user 
# also removes the user's mail spool file.
# See comments in /etc/login.defs
#
# "nopen" stands to avoid reporting new mail when su'ing to another user
session    optional   pam_mail.so nopen

su -

su と同じく新ユーザーでシェルが実行されるんだけど、ログインシェルとして実行される。

カレントディレクトリも新ユーザーのホームディレクトリになる。

シェルが bash の場合は /etc/profile, ~/.bash_profile, ~/.bash_login, ~/.profile などが実行される。

環境変数はクリアされるが、ひとつだけ例外があって TERM 環境変数だけは引き継がれる。TERM までクリアされちゃうと端末制御がおかしくなってしまうので…。

sudo

別のユーザーでコマンドを実行するためのコマンド。自分は「すーどぅー」と呼んでいる。
su がシェルを実行するのに対して sudo は引数で実行するコマンドを指定する。

入力するパスワードは元のユーザー(sudo を実行したユーザー)のパスワード。

~% sudo id
[sudo] password for tmtms: (元のユーザーのパスワード)
uid=0(root) gid=0(root) groups=0(root)
~% 

デフォルトでは root になるが、-u オプションでユーザーを指定できる。

~% sudo -u hoge id
[sudo] password for tmtms: (元のユーザーのパスワード)
uid=1001(hoge) gid=1001(hoge) groups=1001(hoge)
~% 

カレントディレクトリは変わらない。

環境変数はいろいろ引き継がれる(後述)。

自分のパスワードを入力すればいいので、他のユーザー、とくに root のパスワードを知らなくても root でコマンドを実行できるのが便利。

といっても誰でも root でコマンドを実行できちゃ困るんで、/etc/sudoers で sudo を使える人を制限している。
Ubuntu の場合は admin グループや sudo グループに属しているユーザーが sudo を使用できる。

Ubuntu は root にはパスワードは設定されないので su は使えない。root での作業が必要な場合は sudo を使うことになる。

sudo に一度パスワードを入力すると、一定時間(デフォルトでは15分間)パスワードなしで実行できるので、連続して sudo を実行するときにもいちいちパスワードが聞かれなくて便利。sudo -K で時間をリセットすることができる。

どうせ聞かれると思って先走ってパスワードを入力すると、まだ前回実行時から15分経ってなくて、パスワード文字列が端末に表示されるという事故もときどき…。

sudo -s

root でコマンドを実行したいときに sudo をつけるだけで実行できるんでいいんだけど、root でシェルの機能(ワイルドカードとかリダイレクトとか)を使いたいこともあって、sudo で対話型シェルを実行したい。

そのときに例の sudo su が使われることがある。

sudo su は root 権限で su を実行し、su は root でシェルを実行するので、結果的に sudo を使って root でシェルを起動することになる。

~% sudo su
[sudo] password for tmtms: (元のユーザーのパスワード)
root@hostname:/home/tmtms# 

まあ別にいいんだけど、それなら sudo bash の方がシンプルな気がする。タイプ数が多いけど。

~% sudo bash
[sudo] password for tmtms: (元のユーザーのパスワード)
root@hostname:/home/tmtms# 

で、sudo には -s というオプションがあって、シェルを起動することができる。sudo su よりもこっちの方が良さそう。

ただし、このとき起動されるシェルは su と違って sudo 実行時の SHELL 環境変数の値が使用される。

~% sudo -s
[sudo] password for tmtms: (元のユーザーのパスワード)
hostname# 

sudo -i

sudo には -i というオプションもあって、これは su - と同じようにシェルがログインシェルとして起動される。
シェルはちゃんと新ユーザーのデフォルトシェルで、カレントディレクトリも新ユーザーのホームディレクトリになる。

% sudo -i
[sudo] password for tmtms: (元のユーザーのパスワード)
root@hostname:~# 

sudo の環境変数

root で sudo -V を実行すると sudo の設定がいろいろ表示される。引き継がれる環境変数もここで出力される。

~% sudo -V
Sudo バージョン 1.9.5p2
sudoers ポリシープラグイン  バージョン 1.9.5p2
sudoers ファイル文法バージョン 48
Sudoers I/O plugin version 1.9.5p2
Sudoers audit plugin version 1.9.5p2
~% sudo sudo -V 
Sudo バージョン 1.9.5p2
configure オプション: --build=x86_64-linux-gnu --prefix=/usr --includedir=${prefix}/include --mandir=${prefix}/share/man --infodir=${prefix}/share/info --sysconfdir=/etc --localstatedir=/var --disable-option-checking --disable-silent-rules --libdir=${prefix}/lib/x86_64-linux-gnu --libexecdir=${prefix}/lib/x86_64-linux-gnu --disable-maintainer-mode --disable-dependency-tracking -v --with-all-insults --with-pam --with-fqdn --with-logging=syslog --with-logfac=authpriv --with-env-editor --with-editor=/usr/bin/editor --with-exampledir=/usr/share/doc/sudo/examples --with-timeout=15 --with-password-timeout=0 --with-passprompt=[sudo] password for %p:  --without-lecture --with-tty-tickets --disable-root-mailer --enable-admin-flag --with-sendmail=/usr/sbin/sendmail --with-rundir=/run/sudo --libexecdir=/usr/lib --with-sssd --with-sssd-lib=/usr/lib/x86_64-linux-gnu --enable-zlib=system --with-selinux --with-linux-audit --enable-tmpfiles.d=yes MVPROG=/bin/mv
sudoers ポリシープラグイン  バージョン 1.9.5p2
sudoers ファイル文法バージョン 48

sudoers のパス: /etc/sudoers
認証方法: 'pam'
ログ記録時に syslog を使用する場合の syslog ファシリティ: authpriv
ログ記録時に syslog を使用する場合の syslog プライオリティ: notice
ユーザー認証に失敗したと時に使用される syslog プライオリティ: alert
ユーザー認証に失敗した場合にメールを送信します
ユーザー他 sudoers 内に存在しない場合にメールを送信します
ユーザーが最初に sudo を実行した時に講義を行う
デフォルトでユーザーが認証されていることを必要とします
root が sudo を実行するかもしれません
役に立つエラーメッセージを表示するためにいくつかの情報を収集することを許可します
sudoers ファイルに完全修飾ホスト名 (FQDN) を要求します
visudo が EDITOR 環境変数を尊重して使用します
LOGNAME および USER 環境変数を設定します
ログファイルの行頭から改行までの長さ (0 の場合は改行しない): 80
認証タイムスタンプのタイムアウト値: 15.0 分
パスワード入力要求のタイムアウト値: 0.0 分
パスワード入力の試行回数: 3
使用する umask 値 (0777 の場合はユーザーの設定値を使用します): 022
メールプログラムのパス: /usr/sbin/sendmail
メールプログラムの引数フラグ: -t
メールの送信先アドレス: root
メールの件名 (Subject) 行: *** SECURITY information for %h ***
パスワードを間違った時のメッセージ: すみません、もう一度試してください。
受講状況ディレクトリのパス: /var/lib/sudo/lectured
認証タイムスタンプディレクトリのパス: /run/sudo/ts
パスワード入力要求時に表示される文字列: [sudo] %p のパスワード: 
コマンドを実行するデフォルトの変更先ユーザー: root
ユーザーの $PATH を上書きする時の値: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
visudo で使用されるエディターのパス: /usr/bin/editor
'list' 疑似コマンド使用するためにパスワードを要求される時: any
'verify' 疑似コマンドを使用するためにパスワードを要求される時: all
3 以上の値をもつファイル記述子をコマンド実行前に閉じます
環境変数の集合をデフォルトに設定します
安全性の確認を行う環境変数:
	TZ
	TERM
	LINGUAS
	LC_*
	LANGUAGE
	LANG
	COLORTERM
削除する環境変数:
	*=()*
	RUBYOPT
	RUBYLIB
	PYTHONUSERBASE
	PYTHONINSPECT
	PYTHONPATH
	PYTHONHOME
	TMPPREFIX
	ZDOTDIR
	READNULLCMD
	NULLCMD
	FPATH
	PERL5DB
	PERL5OPT
	PERL5LIB
	PERLLIB
	PERLIO_DEBUG
	JAVA_TOOL_OPTIONS
	SHELLOPTS
	BASHOPTS
	GLOBIGNORE
	PS4
	BASH_ENV
	ENV
	TERMCAP
	TERMPATH
	TERMINFO_DIRS
	TERMINFO
	_RLD*
	LD_*
	PATH_LOCALE
	NLSPATH
	HOSTALIASES
	RES_OPTIONS
	LOCALDOMAIN
	CDPATH
	IFS
保護する環境変数:
	XAUTHORIZATION
	XAUTHORITY
	PS2
	PS1
	PATH
	LS_COLORS
	KRB5CCNAME
	HOSTNAME
	DPKG_COLORS
	DISPLAY
	COLORS
sudoers を構文解析する時に使用するロケール: C
I/O ログを zlib を使用して圧縮します
入出力 (I/O) ログを保存するディレクトリです:/var/log/sudo-io
入出力 (I/O) ログを保存するファイルです:%{seq}
pty を割り当てた時に utmp/utmpx ファイルに記録を加えます
利用する PAM サービス名: sudo
ログインシェルで利用する PAM サービス名: sudo
ターゲットユーザーの PAM 資格情報による認証を試みる
実行するコマンドのために新しい PAM セッションを生成する
PAM アカウント検証管理を実行しています
sudoers のネットグループサポートを有効にする
ファイルを sudoedit で編集するときに親ディレクトリが書き込み可能か確かめる
監査ログファイルへの書き込みができなくても、コマンドの実行を許可する
ログファイルへの書き込みができなくても、コマンドの実行を許可する
ログエントリーがこの値より長くなると、複数の syslog メッセージに分割されます: 960
I/O ログのファイルモード: 0600
コマンドの実行時にパスでなくファイル記述子を使う: digest_only
認証タイムスタンプのタイプ: tty
ユーザー名の検索で大文字小文字を同一視する
グループ名の検索で大文字小文字を同一視する
コマンドが sudoers で許可された場合にログに記録します
コマンドが sudoers で拒否された場合にログに記録します
Sudo ログサーバーのタイムアウト、単位は秒: 30
ログサーバーに接続したソケットで SO_KEEPALIVE ソケットオプションを有効にする
ログサーバーの証明書が有効か検証する
PAMのリモートユーザーを sudo を実行しているユーザーに設定
生成するログの書式: sudo
Enable SELinux RBAC support

ローカル IP アドレスとネットマスクの組:
	xxx.xxx.x.xxx/xxx.xxx.xxx.x
	xxx.xxx.x.xxx/xxx.xxx.xxx.x
	xxx.xx.x.x/xxx.xxx.x.x
	xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxx/xxxx:xxxx:xxxx:xxxx::
	xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/xxxx:xxxx:xxxx:xxxx::
	xxxx::xxxx:xxxx:xxxx:xxxx/xxxx:xxxx:xxxx:xxxx::
	xxxx:xxxx:xxxx:xxxx:xxxx:xxx:xxxx:xxxx/xxxx:xxxx:xxxx:xxxx::
	xxxx::xxxx:xxxx:xxxx:xxxx/xxxx:xxxx:xxxx:xxxx::

Sudoers I/O plugin version 1.9.5p2
Sudoers audit plugin version 1.9.5p2

Discussion