bashスクリプトでrootとして実行されているかどうかを確認する方法


275

ルートレベルのアクセス許可を必要とするスクリプトを作成していますが、スクリプトがルートとして実行されない場合に、単に「ルートとして実行してください」と表示されるようにしたいと考えています。そして終了します。

これが私が探しているもののいくつかの疑似コードです:

if (whoami != root)
  then echo "Please run as root"

  else (do stuff)
fi

exit

どうすればこれを(クリーンかつ安全に)最善の方法で達成できますか?ありがとう!

ああ、明確にするために:(何かを行う)部分には、それ自体がrootを必要とするコマンドの実行が含まれます。したがって、通常のユーザーとして実行すると、エラーが発生します。これは、スクリプト内でsudoを使用せずに、rootコマンドを必要とするスクリプトを適切に実行することを目的としています。構文糖を探しているだけです。


8
(1)root以外では実行できないようにする(2)さらにアクセス権を準備する。(3)rootにid -u戻る0
Wrikken 2013

回答:


404

$ EUID環境変数は、現在のユーザーのUIDを保持します。ルートのUIDは0です。スクリプトでは次のようなものを使用します。

if [ "$EUID" -ne 0 ]
  then echo "Please run as root"
  exit
fi

注:あなたが取得する場合2: [: Illegal number:、あなたが持っている場合はチェックを#!/bin/sh先頭にし、それを変更します#!/bin/bash


適切な権限とこれを使用することは、セキュリティの二重層のようです
Kolob Canyon

25
文字列を文字列と比較し、数値を数値と比較する方が良いと思います。二重括弧を使用すると、引用符なしで>を直接使用できます[[$ EUID> 0]]
Sergio Abreu

7
2: [: Illegal number:セルジオのバージョンに変更するまで警告を受けました。
alexeydemin 2017年

1
@ thekiwi5000セミコロンはthen、条件と同じ行にある場合にのみ必要です...
ptierno

1
@StephenAngelico Sudoは動作するはずです。$ sudo echo $ EUIDを実行してテストしている場合は、これは悪いテストであり、コマンドがsudoに渡される前に$ EUIDが展開されるため、失敗します。echo $ EUIDをテストスクリプトに入れて、sudoで実行してみてください。
user1169420

79

bashスクリプトでは、実行中のユーザーがrootであるかどうかを確認する方法がいくつかあります。

警告として、rootユーザー名を使用してユーザーがrootであるかどうかを確認しないでください。ID 0のユーザーが呼び出されることを保証するものは何もありませんroot。これは非常に強力な規則ですが、広く使用されていますが、誰でもスーパーユーザーの名前を別の名前に変更できます。

私はbashを使用する場合の最良の方法は$EUID、manページからを使用することだと思います。

EUID   Expands to the effective user ID of the current  user,  initialized
       at shell startup.  This variable is readonly.

これは$UID変更可能な方法よりも優れており、スクリプトを実行している実際のユーザーを反映していません。

if (( $EUID != 0 )); then
    echo "Please run as root"
    exit
fi

この種の問題にアプローチする方法はsudo、rootとして実行されていないときにコマンドに挿入することです。次に例を示します。

SUDO=''
if (( $EUID != 0 )); then
    SUDO='sudo'
fi
$SUDO a_command

この方法では、スーパーユーザーを使用する場合、またはsudo通常のユーザーが実行する場合に、rootがコマンドを実行します。

スクリプトを常にrootで実行する場合は、それに応じて権限を設定するだけです(0500)。


スクリプトを実行しようとしている人にsudo権限がない場合、これによりエラーがスローされ、コマンドは実行されませんか?確認したいだけですが、私は正しく理解しています。
Caperneoignis

1
この答えが100%完全に正しいとは思いません。Bash 4.2.46を使用するRHEL7.2では... printf $EUIDsudoの有無にかかわらず、自分のUIDが返されます。私が使用する場合id -uはUIDを取得し、sudoでそれを呼び出すと0が返されます。私は何か間違ったことをしましたか?
0xSheepdog

4
@ 0xSheepdog、bash cliでは、$ EUID変数の展開が最初に解決され、次にsudoがユーザーを変更する可能性があります。したがって、そのような動作が得られますが、スクリプトでは、すべてが正常に動作します。
Alexander Bird

@AlexanderBird良い点、ありがとう!実際のテストは行わず、自分の経験を報告しました。
0xSheepdog

3
変数のローカルシェル展開を防ぐために、テストに「herestring」を使用します。と比較sudo bash <<<'echo $EUID'してくださいbash <<<'echo $EUID'。tldp.org/LDP/abs/html/x17837.htmlのheredocのようなherestringの詳細
Bruno Bronosky 2017年

75

いくつかの回答が出されていますが、最善の方法は次のとおりです。

  • id -u
  • ルートとして実行すると、IDとして0が返されます。

これは他の方法よりも信頼性が高いようで、スクリプトを実行しても、idが0を返すようですsudo


1
グレートこれが最善の答えは
ダン・オルテガ

59
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

または

if [[ `id -u` -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

:)


あなたはジェレミー・J・スターチャーの答え をこの部分と統合することを検討することができます、結局それは常に同じものです
本当に素晴らしい

ターミナルから、何かを前に付けるのを忘れたときは、上向き矢印を押して行の先頭に移動して手動で追加するのではなく、入力sudoするだけsudo !!でうまくいくことがわかりsudo ます。それがBASHなのかSUDOなのかはわかりませんが、ほとんどの場合は機能します。
0xSheepdog 2016

@ 0xSheepdog:これはBashのものです(そしてIIRCが発生したcshなどの他のいくつかのシェルの機能です)。
追って通知があるまで一時停止。

全体として、バッククォートされた部分を全体として削除し、ok行をに書き直しif [ "$(id -u)" -ne 0 ]; then echo 'Please run as root.' >&2; exit 1; fiます。乾杯。
LinuxSecurityFreak

29

@wrikkenがコメントで述べたように、id -uルートのチェックははるかに優れています。

さらに、を適切に使用するとsudo、スクリプトをチェックして、rootとして実行されているかどうかを確認できます。そうでない場合は、経由sudoで自分自身を呼び戻し、root権限で実行します。

スクリプトの機能に応じてsudo、スクリプトが必要とする特殊なコマンドのエントリを設定することもできます。


プログラムにそれ自体をリコールさせる優雅な方法はありますか?おそらく、プログラムへの絶対パスを持つbash変数がいくつかありますか?
Nathan

1
テストするBASHプロンプトの近くではありません$0が、実行中のスクリプトの名前がわかります。ここにあなたを助けるかもしれないいくつかの例があります。
ジェレミーJスターチャー2013

25

rootであるユーザーの簡単なチェックがあります。

[[ stuff ]]構文はbashでチェックを実行するための標準的な方法です。

error() {
  printf '\E[31m'; echo "$@"; printf '\E[0m'
}

if [[ $EUID -eq 0 ]]; then
    error "Do not run this as the root user"
    exit 1
fi

これは、失敗した場合に1で終了することも想定しています。error(あなたは私に言わせれば必要ありませんが、かなり上品)関数は、赤にいくつかの才能そのセット出力テキストです。


そのerrorコマンドは何ですか?私のシステムにはないようです。。。
ruakh 2013

ああ、それはほんの小さなことです。それほど重要ではありませんが、添付します。
Slater Victoroff 2013

4
それはいいね!いくつかの改善を提案する場合は、次のようにします。(2)標準出力ではなく標準エラーに書き込みます。(3)標準エラーが端末である場合にのみ色を設定します(ログファイルなどにエスケープ文字を書き込む危険を冒すのではなくless)。(4)背景色を設定します。これにより、ユーザーの端末の背景色に関係なく、テキストが読みやすくなります。だから、のようなものfunction error () { if [[ -t 2 ]] ; then echo $'\033[31;2;47m'"$@"$'\033[0m' ; else echo "$@" ; fi >&2 ; }。(必要に応じて調整します)
ruakh 2013

3
それは "-eq"ではなく "-ne"であるべきではありませんか?
カルロスレンドン2014年

2
@CarlosRendon Slaterのコードは、何かがrootとして実行されるのを防ぐためのものです。(これはOPが求めていたものとは逆ですが、チェックの方法は同じです。)
Joshua Taylor

11

非常に単純な方法は単に置く:

if [ "$(whoami)" == "root" ] ; then
    # you are root
else
    # you are not root
fi

代わりにこれを使用する利点はid、特定の非rootユーザーがコマンドを実行しているかどうかも確認できることです。例えば。

if [ "$(whoami)" == "john" ] ; then
    # you are john
else
    # you are not john
fi

文字列「root」でユーザーをテストする場合、「root」という名前のユーザーを実行することを許可していませんか?
pcarvalho

「;」を忘れた ifの後
Triskeldeian、

1
@peteroak root以外にrootと名付けられる人は誰ですか?
ptierno 2016

3
whoamiを使用するのではなく、実際に質問に答えるための+1 id。このwhoamiコマンドは、root 以外のユーザーを名前で確認するために使用できます。
Jez

10

0-公式のGNU Linux文書を読んでください。正しく行うには多くの方法があります。

1-解釈のエラーを回避するために、シェル署名を必ず入れてください。

 #!/bin/bash

2-これは私のスクリプトです

#!/bin/bash 

if [[ $EUID > 0 ]]; then # we can compare directly with this syntax.
  echo "Please run as root/sudo"
  exit 1
else
  #do your stuff
fi

10

この回答では、それは明確にしましょう、私は推測読者が読み取ることができbash、およびPOSIXのようなシェルスクリプトdash

投票数の多い回答はその多くを説明するのに優れているので、ここで説明することはあまりないでしょう。

しかし、さらに説明することがあれば、遠慮なくコメントしてください。ギャップを埋めるために最善を尽くします。


bashパフォーマンスと信頼性のための最適化されたオールラウンド(だけでなく)ソリューション。すべてのシェル互換

新しいソリューション:

# bool function to test if the user is root or not
is_user_root () { [ ${EUID:-$(id -u)} -eq 0 ]; }

ベンチマーク(ファイルに保存is_user_root__benchmark

###############################################################################
##                          is_user_root() benchmark                         ##
##                  Bash is fast while Dash is slow in this                  ##
##          Tested with Dash version 0.5.8 and Bash version 4.4.18           ##
##                     Copyright: 2020 Vlastimil Burian                      ##
##                      E-mail: info@vlastimilburian.cz                      ##
##                             License: GPL-3.0                              ##
##                               Revision: 1.0                               ##
###############################################################################

# intentionally, the file does not have executable bit, nor it has no shebang
# to use it, please call the file directly with your shell interpreter like:

# bash is_user_root__benchmark
# dash is_user_root__benchmark

# bool function to test if the user is root or not
is_user_root () { [ ${EUID:-$(id -u)} -eq 0 ]; }

# helper functions
print_time   () { date +"%T.%2N"; }
print_start  () { printf '%s' 'Start  : '; print_time; }
print_finish () { printf '%s' 'Finish : '; print_time; }

readonly iterations=10000

printf '%s\n' '______BENCHMARK_____'
print_start

i=1; while [ $i -lt $iterations ]; do
    is_user_root
    i=$((i + 1))
done

print_finish

元のソリューション:

#!/bin/bash

is_user_root()
# function verified to work on Bash version 4.4.18
# both as root and with sudo; and as a normal user
{
    ! (( ${EUID:-0} || $(id -u) ))
}

if is_user_root; then
    echo 'You are the almighty root!'
else
    echo 'You are just an ordinary user.'
fi

^^^取り消されたソリューションはスピードアップしないことが証明されましたが、長い間使用されてきたので、必要な限りここに置いておきます。


説明

コマンドを実行してPOSIXでユーザーIDを見つけるよりも、$EUID標準bash変数である有効なユーザーID番号を読み取る方が何倍も高速であるため、このソリューションは両方を適切にパックされた関数に結合します。が何らかの理由で使用できない場合に限り、コマンドが実行され、状況に関係なく適切な戻り値が取得されます。id -u$EUIDid -u


何年にもわたってOPがこのソリューションを投稿した理由

まあ、私が正しく見れば、上記のコードの一部が欠けているようです。

ご覧のとおり、考慮しなければならない変数はたくさんあります。その1つは、パフォーマンスと信頼性の組み合わせです。


ポータブルPOSIXソリューション+上記の関数の使用例

#!/bin/sh

# bool function to test if the user is root or not (POSIX only)
is_user_root() { [ "$(id -u)" -eq 0 ]; }

if is_user_root; then
    echo 'You are the almighty root!'
    exit 0 # unnecessary, but here it serves the purpose to be explicit for the readers
else
    echo 'You are just an ordinary user.' >&2
    exit 1
fi

結論

あなたがおそらくそれを好きではないのと同じくらい、Unix / Linux環境は多くの多様化を遂げました。bashとても好きな人がいることを意味し、彼らは移植性(POSIXシェル)さえ考えていません。私のような他の人はPOSIXシェルを好みます。今日では個人の選択とニーズの問題です。


6

スクリプトが本当にrootアクセスを必要とする場合、そのファイル許可はそれを反映する必要があります。root以外のユーザーがrootスクリプトを実行可能にすることは、危険なことです。ifチェックでアクセスを制御しないことをお勧めします。

chown root:root script.sh
chmod u=rwx,go=r script.sh

4
誰かが彼らの許可を持っているならこれはうまくいきますが、777爆弾の使いすぎはこのチェックを最初から間違いをする種類のユーザーに対して少し欠陥があるように感じます。
Slater Victoroff 2013

7
これは、ユーザーが実行可能スクリプトを実行していることを前提としています。ユーザーが電話をかけるだけでbash /path/to/scriptも、実行できますo=r
ptierno

5

スクリプトをrootだけが実行できるようにする簡単な方法の1つは、スクリプトを次の行で開始することです。

#!/bin/su root


1
なぜこの回答がより高く投票されないのか、私は興味がありますか?最もシンプルでクリーンなようです。ここに欠点はありますか?
Bassinator

@Bassinator特定のnixでは動作しないと言う人もいると思いますが、今のところ私のLinuxでは問題なく動作しています。それを試してみてください!たぶんこの答えはレースの後半に来たかもしれませんが、私はコミュニティに簡単なノウリードを追加しようとしています(このスレッドのほとんどのように、同様の答えを与えるのではなく:/)。お使いのマシンで動作します
alexandre1985

@TamusJRoyceルートとして実行しているかどうかをチェックし、スクリプトをルートとしてのみ実行することを強制しないことを目標とする場合、なぜすべての回答で、ルートとして実行しているかどうかをチェックした後、スクリプトを作成するのexitですか?そして、それでもそれらの答えは支持されていますか?スクリプトをrootとして実行することを暗黙のうちに望まないでしょう。したがって、私はその考え方に従い、より単純な答えを採用しています。しかし、そうです、上記のより詳細な回答から学ぶこともできます
alexandre1985

@ alexandre1985その通りです。シナリオ:rootとして実行している場合、スクリプトをインストールする方法を尋ねられたときにスクリプトをデフォルトでグローバルにインストールする必要がある場合があります。それ以外の場合は、デフォルトでローカルにインストールされます。Enterキーを押す代わりに、ユーザーはそれをグローバルまたはローカルにインストールすることを選択できます。ただし、デフォルトが好きな場合は、Enterキーを押すことができます。また、パスワードの入力は求められません。あなたが(タイトルごとに)ルートである場合、あなたのシバンは決して「チェック」しません。しかし、私はまだこの答えが役に立つと思います。
TamusJRoyce

@TamusJRoyceはあなたのコメントを完全に理解します。確かに懸念事項であり、このソリューションはそのユースケース用ではありません。あなたは私の視点を開きました。あなたが正しいです。ありがとう
alexandre1985

4

次のコードを試してください:

if [ "$(id -u)" != "0" ]; then
    echo "Sorry, you are not root."
    exit 1
fi

または

if [ `id -u` != "0" ]; then
    echo "Sorry, you are not root."
    exit 1
fi

3

私が知る限り、それを確認する正しい方法は次のとおりです。

if [ $(id -u) = "0" ]; then
    echo "You are root"
else
    echo "You are NOT root"
fi

ここで「ルートのテスト」セクションを参照してください。

http://linuxcommand.org/lc3_wss0080.php


1
置き換える= "0"-eq 0
LinuxSecurityFreak

1
@LinuxSecurityFreak、なぜ私がそれをするべきかを説明するなら、私はそれを置き換えます。
WebBrother

2

id -uwhoamiandroidのような一部のシステムではrootという単語が提供されない場合があるため、はよりも優れています。

例:

# whoami
whoami
whoami: unknown uid 0

0
#!/bin/bash

# GNU bash, version 4.3.46
# Determine if the user executing this script is the root user or not

# Display the UID
echo "Your UID is ${UID}"

if [ "${UID}" -eq 0 ]
then
    echo "You are root"
else
    echo "You are not root user"
fi

編集者注:二重括弧が必要ない場合は、コードの移植性のために単一括弧を使用してください。


3
すでにいくつかの回答がある5年前の質問に代替回答を提供した理由を説明していません。
Styphon

0

rootかどうかを確認し、rootでない場合は終了します。

if ((EUID != 0)); then
    echo "Root or Sudo  Required for script ( $(basename $0) )"
    exit
fi

または、この例では、ルートの場所にディレクトリを作成してから、権限が昇格した後で試します。

rootであるかどうかを確認し、可能でない場合は昇格します。

# Fails to create these dirs (needs sudo)
mkdir /test-dir-$(basename $0)
rmdir /test-dir-$(basename $0)

if ((EUID != 0)); then
    echo "Granting root privileges for script ( $(basename $0) )"
    if [[ -t 1 ]]; then
        sudo "$0" "$@"
    else
        exec 1> output_file
        gksu "$0" "$@"
    fi
    exit
fi
echo "Root privileges granted..."
# Creates Dirs as it now has rights
mkdir /test-dir-$(basename $0)
rmdir /test-dir-$(basename $0)

-1

ルートを確認します。

ROOT_UID=0   # Root has $UID 0.

if [ "$UID" -eq "$ROOT_UID" ]
then
  echo "You are root."
else
  echo "You are just an ordinary user."
fi

exit 0

テストされ、ルートで実行されています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.