環境
OS X YosemiteとLinux(RedHat系)でのテスト。
OS Xでのrootユーザーの有効化についてはAppleのページで確認。
rootユーザーとしてログインして実行した時や、
su
でrootとなった場合、
sudo
でroot権限を持って実行する場合に
スクリプトやプログラムの中でrootかどうか判断したい、と言う状況での話です。
ユーザー名
USER名で判断用とするこんなスクリプト:
1 2 3 4 5 6 |
|
これだと通常ユーザーだとnon-root user!
と出て、
rootでログインして実行するとroot!
と出ます。
ただし、su
でrootになった場合、$USER
の値は元のままなので
これだと失敗します。
$ su
# ./root_check.sh
non-root user!
一方、sudo
で実行すると
一時的にユーザーごと全て変更されるので、
$USER
もroot
に変更されます。
$ sudo ./root_check.sh
root!
sudo echo $USER
の様にコマンドを直接実行してしまうと
引数部分の変数が展開されてからsudo
に渡される形になってしまうので
この場合は本のユーザー名が出てしまいます。
$ sudo echo $USER
user
また、sudo -s
を使うと渡した引数を新たなシェルで実行する様な形になるのですが、
Macの場合、
$ sudo -s 'echo $USER'
root
とシングルクォートで囲って渡すと$USER
部分をそのままの状態で
渡して、その後シェルを立ち上げてecho $USER
を実行する形になり、
結果的にroot
が出ます。
コマンド部分をクォートしないか、ダブルクォートで囲うとまず
$USER
を解釈してからsudo
に渡すのでuser
が出ます。
$ sudo -s "echo $USER"
user
ここでLinuxでやってみると、クォートしない場合は同じ結果ですが、 クォートすると
$ sudo -s 'echo $USER'
みたいなエラーが出てしまいます。 ダブルクォートでも
$ sudo -s "echo $USER"
/bin/bash: echo user: command not found
sudo
の仕様が少し違う様です。
これ以外に$LOGNAME
という環境変数がありますが、
こちらの場合だと、su
した時はroot
になり、
sudo
だと元のユーザー名になります。
ので、これらを使ってやる方法はちょっと上手く行きません。
UID
そこで、$UID
を使ってみます。
1 2 3 4 5 6 |
|
これだとsu
した時も$UID
は0になり、rootとそれ以外のユーザーを
区別することが出来ます。
普通はしないですが、rootのユーザー名を変更した場合にもこれだと大丈夫。
Pythonなら
1 2 3 4 5 6 |
|
ついでにPythonでのユーザー名等の取り方等一覧。
1 2 3 4 5 6 7 8 9 |
|
$ ./user_check.py # Normal user
501
user
user
user
user
$ sudo ./user_check.py
Password:
0
root
user
root
root
$ su
Password:
$ ./user_check.py
0
root
user
user
user
EUID
UNIXには$UID
に加えて$EUID
という
実効UIDがあります。
実効UID (effective UID)
実効UID (euid) と実効GID (egid) はファイル作成とファイルアクセスに影響する。ファイル作成時、カーネルはそのファイルの所有者を作成しているプロセスの実効UIDと実効GIDで設定する。ファイルアクセス時、カーネルはプロセスの実効UIDと実効GIDでアクセス権の有無を判断する。
と、Wikipediaにあります。
ただ、上のPythonスクリプトで
print os.geteuid()
を加えて実行してみても全てgetuid
と同じ結果になりました。
ここにEUIDについて色々試したものが載ってますが(ちなみにリンク先ではCでのやり方が書いてあります)、 この通りにやっても上手く再現出来ません。
この辺、自分が何か勘違いしてるのかちょっと理解不足。