rcmdnk's blog
Last update

I Am Root: Linux Unix Terminal Nerd Geek Sysadmin Notebook Journal Diary Logbook

スクリプトやプログラムの中で実行中のユーザーがrootかどうか 判断する方法について。

surootになったつもりでおこなったら上手く行かなかった事等。

環境

OS X YosemiteとLinux(RedHat系)でのテスト。

OS Xでのrootユーザーの有効化についてはAppleのページで確認。

Mac OS X で「ルート」ユーザを有効にして使用する - Apple サポート

rootユーザーとしてログインして実行した時や、 surootとなった場合、 sudoroot権限を持って実行する場合に スクリプトやプログラムの中でrootかどうか判断したい、と言う状況での話です。

ユーザー名

USER名で判断用とするこんなスクリプト:

root_check.sh
1
2
3
4
5
6
#!/usr/bin/env bash
if [ "$USER" == "root" ];then
  echo "root!"
else
  echo "non-root user!"
fi

これだと通常ユーザーだとnon-root user!と出て、 rootでログインして実行するとroot!と出ます。

ただし、surootになった場合、$USERの値は元のままなので これだと失敗します。

$ su
# ./root_check.sh
non-root user!

一方、sudoで実行すると 一時的にユーザーごと全て変更されるので、 $USERrootに変更されます。

$ 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を使ってみます。

root_check.sh
1
2
3
4
5
6
#!/usr/bin/env bash
if [ "$UID" -eq 0 ];then
  echo "root!"
else
  echo "non-root user!"
fi

これだとsuした時も$UIDは0になり、rootとそれ以外のユーザーを 区別することが出来ます。

普通はしないですが、rootのユーザー名を変更した場合にもこれだと大丈夫。

Pythonなら

root_check.py
1
2
3
4
5
6
#!/usr/bin/env python
import os
if os.getuid() == 0:
  print "root!"
else:
  print "non-root user!"

ついでにPythonでのユーザー名等の取り方等一覧。

user_check.py
1
2
3
4
5
6
7
8
9
#!/usr/bin/env python

import os
import pwd
print os.getuid()
print pwd.getpwuid(os.getuid())[0]
print os.getlogin()
print os.environ.get('LOGNAME')
print os.environ.get('USER')
$ ./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と同じ結果になりました。

Linuxの実効ユーザIDについて実験してみた ブーログ

ここにEUIDについて色々試したものが載ってますが(ちなみにリンク先ではCでのやり方が書いてあります)、 この通りにやっても上手く再現出来ません。

この辺、自分が何か勘違いしてるのかちょっと理解不足。

Sponsored Links
Sponsored Links

« sentakuで選択項目数が多い時にページ表示の様に一気に表示変更する様にした MacでiTerm2上でHyperSwitch等が使えない問題が治っていたのでターミナルからiTerm2へ出戻りした »

}