So überprüfen Sie, ob in einem Bash-Skript als Root ausgeführt wird

273

Ich schreibe ein Skript, für das Berechtigungen auf Stammebene erforderlich sind, und ich möchte es so gestalten, dass, wenn das Skript nicht als root ausgeführt wird, einfach "Bitte als root ausführen" angezeigt wird. und geht.

Hier ist ein Pseudocode für das, wonach ich suche:

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

  else (do stuff)
fi

exit

Wie könnte ich dies am besten (sauber und sicher) erreichen? Vielen Dank!

Ah, nur um zu verdeutlichen: Der (do stuff) Teil würde das Ausführen von Befehlen beinhalten, die an und für sich root erfordern. Wenn Sie es also als normaler Benutzer ausführen, wird nur ein Fehler angezeigt. Dies ist nur dazu gedacht, ein Skript sauber auszuführen, für das Root-Befehle erforderlich sind, ohne dass sudo im Skript verwendet wird. Ich suche nur nach syntaktischem Zucker.

Nathan
quelle
8
(1) mache es nicht ausführbar durch irgendetwas anderes als root (2) arrangiere auch weitere Berechtigungen. (3) id -ugibt 0für root zurück.
Wrikken

Antworten:

403

Die Umgebungsvariable $ EUID enthält die UID des aktuellen Benutzers. Die UID von Root ist 0. Verwenden Sie in Ihrem Skript Folgendes:

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

Hinweis: Wenn Sie erhalten, 2: [: Illegal number:überprüfen Sie, ob Sie #!/bin/shoben haben, und ändern Sie es in #!/bin/bash.

ptierno
quelle
Es scheint, dass gute Berechtigungen und dies eine doppelte Sicherheitsebene sind
Kolob Canyon
25
Ich denke, es ist besser, String mit String, Nummer mit Nummer zu vergleichen. Mit doppelten Klammern können Sie> direkt ohne Anführungszeichen verwenden [[$ EUID> 0]]
Sergio Abreu
7
Ich wurde 2: [: Illegal number:gewarnt, bis ich es auf Sergios Version änderte.
Alexeydemin
1
@ thekiwi5000 Das Semikolon ist nur erforderlich, wenn das thenin der gleichen Zeile wie die Bedingung ist ...
ptierno
1
@ StephenAngelico Sudo sollte funktionieren. Wenn Sie es testen, indem Sie $ sudo echo $ EUID ausführen; Das ist ein schlechter Test und wird fehlschlagen, da $ EUID erweitert wird, bevor der Befehl an sudo übergeben wird. Versuchen Sie, echo $ EUID in ein Testskript einzufügen und dieses mit sudo auszuführen.
user1169420
79

In einem Bash-Skript haben Sie verschiedene Möglichkeiten, um zu überprüfen, ob der laufende Benutzer root ist.

Überprüfen Sie als Warnung nicht, ob ein Benutzer root ist, indem Sie den rootBenutzernamen verwenden. Nichts garantiert, dass der Benutzer mit der ID 0 angerufen wirdroot . Es ist eine sehr starke Konvention, die weitgehend befolgt wird, aber jeder kann den Superuser in einen anderen Namen umbenennen.

Ich denke, der beste Weg, wenn Sie Bash verwenden, ist die Verwendung $EUIDvon der Manpage:

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

Dies ist ein besserer Weg als $UIDder, der geändert werden könnte und nicht den tatsächlichen Benutzer widerspiegelt, der das Skript ausführt.

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

Ein Weg, wie ich mich dieser Art von Problem nähere, besteht sudodarin, meine Befehle einzufügen, wenn sie nicht als root ausgeführt werden. Hier ist ein Beispiel:

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

Auf diese Weise wird mein Befehl von root ausgeführt, wenn der Superuser verwendet wird, oder von sudo wenn er von einem normalen Benutzer ausgeführt wird.

Wenn Ihr Skript immer von root ausgeführt werden soll, legen Sie einfach die entsprechenden Rechte fest ( 0500).

sberder
quelle
Wenn die Person, die versucht, das Skript auszuführen, keine Sudo-Berechtigungen hat, wird der Fehler ausgelöst und der Befehl wird nicht ausgeführt. Ich möchte nur sichergehen, dass ich es richtig verstehe.
Caperneoignis
1
Ich bin nicht sicher, ob diese Antwort zu 100% richtig ist. Auf RHEL7.2 mit Bash 4.2.46 ... wenn ich printf $EUIDmit oder ohne sudo bin, bekomme ich meine eigene UID zurück. Wenn ich benutze, id -ubekomme ich meine UID und wenn ich sie mit sudo aufrufe, bekomme ich 0 zurück. Habe ich etwas falsch gemacht?
0xSheepdog
4
@ 0xSheepdog, es ist möglich, dass auf der Bash-Cli die $ EUID-Variablenerweiterung zuerst aufgelöst wird und dann sudo den Benutzer wechselt. Daher würden Sie dieses Verhalten erhalten, aber in Skripten würde immer noch alles gut funktionieren.
Alexander Bird
@ AlexanderBird Guter Punkt, danke! Ich habe keine wirklichen Tests durchgeführt, sondern nur über meine Erfahrungen berichtet.
0xSheepdog
3
Verwenden Sie für Ihren Test einen "Herestring", um eine lokale Shell-Erweiterung der Variablen zu verhindern. Vergleiche sudo bash <<<'echo $EUID'mit bash <<<'echo $EUID'. Mehr über den Heredoc-ähnlichen Herestring unter tldp.org/LDP/abs/html/x17837.html
Bruno Bronosky
74

Es wurden einige Antworten gegeben, aber es scheint, dass die beste Methode darin besteht, Folgendes zu verwenden:

  • id -u
  • Wenn als root ausgeführt, wird eine ID von 0 zurückgegeben.

Dies scheint zuverlässiger zu sein als die anderen Methoden, und es scheint, dass es eine ID von 0 zurückgibt, selbst wenn das Skript ausgeführt wird sudo.

Nathan
quelle
Großartig, das ist die beste Antwort
Dan Ortega
58
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

oder

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

:) :)

Dale_Reagan
quelle
Sie könnten erwägen, Jeremy J Starchers Antwort in diesen Teil zu integrieren, am Ende ist es immer das gleiche Zeug ...
wirklich schön
Ich weiß, dass ich vom Terminal aus, wenn ich vergesse, etwas mit dem Präfix zu versehen, sudoeinfach tippen kann sudo !!und es die Arbeit für mich erledigt, anstatt den Aufwärtspfeil zu drücken, zum Zeilenanfang zu gehen und sudo von Hand hinzuzufügen . Ich bin mir nicht sicher, ob das eine BASH-Sache oder eine SUDO-Sache ist, aber es funktioniert fast immer.
0xSheepdog
@ 0xSheepdog: Es ist eine Bash-Sache (und ein Merkmal einiger anderer Shells wie csh, wo IIRC seinen Ursprung hat).
Bis auf weiteres angehalten.
Alles in allem würde ich den Backticked-Teil als Ganzes entfernen und die OK-Zeile neu schreiben if [ "$(id -u)" -ne 0 ]; then echo 'Please run as root.' >&2; exit 1; fi. Prost.
LinuxSecurityFreak
29

Wie @wrikken in seinen Kommentaren erwähnt hat, id -uist eine viel bessere Überprüfung auf root.

Darüber hinaus können Sie bei ordnungsgemäßer Verwendung von sudodas Skript überprüfen lassen, ob es als Root ausgeführt wird. Wenn nicht, lassen Sie es sich über zurückrufen sudound dann mit Root-Berechtigungen ausführen.

Je nachdem, was das Skript tut, besteht eine andere Möglichkeit darin, einen sudoEintrag für die speziellen Befehle einzurichten, die das Skript möglicherweise benötigt.

Jeremy J Starcher
quelle
Gibt es eine anmutige Möglichkeit, ein Programm selbst zurückrufen zu lassen? Vielleicht gibt es eine Bash-Variable mit dem absoluten Pfad zum Programm?
Nathan
1
Ich bin gerade nicht in der Nähe einer BASH-Eingabeaufforderung zum Testen, habe aber $0den Namen des laufenden Skripts. Es gibt einige Beispiele hier , die Ihnen helfen können.
Jeremy J Starcher
25

Es gibt eine einfache Überprüfung, ob ein Benutzer root ist.

Die [[ stuff ]]Syntax ist die Standardmethode zum Ausführen einer Check-in-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

Dies setzt auch voraus, dass Sie mit einer 1 beenden möchten, wenn Sie fehlschlagen. Die errorFunktion ist ein Flair, das den Ausgabetext auf Rot setzt (nicht erforderlich, aber ziemlich edel, wenn Sie mich fragen).

Slater Victoroff
quelle
Was ist das für ein errorBefehl? Mein System scheint es nicht zu haben. . .
Ruakh
Oh, das ist nur ein kleines Flair. Ist nicht so wichtig, aber ich werde es anhängen.
Slater Victoroff
4
Das ist ziemlich toll! Wenn ich ein paar Verbesserungen vorschlagen darf: (1) Verschieben Sie die Newline bis zum Ende; (2) eher auf Standardfehler als auf Standardausgabe schreiben; (3) lessStellen Sie die Farbe nur ein, wenn der Standardfehler ein Terminal ist (anstatt das Risiko einzugehen , Escape-Zeichen in Protokolldateien oder so weiter zu schreiben). und (4) eine Hintergrundfarbe einstellen, so dass der Text unabhängig von der Hintergrundfarbe des Benutzerterminals lesbar ist. Also so etwas wie function error () { if [[ -t 2 ]] ; then echo $'\033[31;2;47m'"$@"$'\033[0m' ; else echo "$@" ; fi >&2 ; }. (Wie gewünscht anpassen.)
Ruakh
3
Sollte das nicht "-ne" statt "-eq" sein?
Carlos Rendon
2
Der Code von @CarlosRendon Slater soll verhindern , dass etwas als Root ausgeführt wird. (Dies ist das Gegenteil von dem, was das OP verlangt hat, aber die Methode der Überprüfung wäre dieselbe.)
Joshua Taylor
11

Sehr einfach ausgedrückt:

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

Der Vorteil dieser Funktion idbesteht darin, dass Sie überprüfen können, ob ein bestimmter Nicht-Root-Benutzer den Befehl ebenfalls ausführt. z.B.

if [ "$(whoami)" == "john" ] ; then
    # you are john
else
    # you are not john
fi
Matthew Trotter
quelle
Wenn Sie den Benutzer mit einer Zeichenfolge "root" testen, dürfen Sie dann niemanden mit dem Namen "root" ausführen?
Pcarvalho
Du hast das ';' nach dem if
Triskeldeian
1
@peteroak wer würde anders als root als root bezeichnet werden?
Ptierno
3
+1 für die tatsächliche Beantwortung der Frage über whoamianstatt zu verwenden id; Der whoamiBefehl kann auch verwendet werden, um nach anderen Benutzern als root nach Namen zu suchen .
Jez
10

0- Lesen Sie die offizielle GNU Linux-Dokumentation. Es gibt viele Möglichkeiten, dies richtig zu machen.

1- Stellen Sie sicher, dass Sie die Shell-Signatur eingeben, um Interpretationsfehler zu vermeiden:

 #!/bin/bash

2- das ist mein Skript

#!/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
Sergio Abreu
quelle
10

In dieser Antwort sei klar, ich gehe davon aus, dass der Leser POSIX- Shell-Skripte lesen bashund mögen kann .dash

Ich glaube, hier gibt es nicht viel zu erklären, da die hoch bewerteten Antworten viel davon gut erklären.

Wenn es jedoch noch etwas zu erklären gibt, zögern Sie nicht zu kommentieren, ich werde mein Bestes tun, um die Lücken zu schließen.


Optimierte Allround- bashLösung (nicht nur ) für Leistung und Zuverlässigkeit; Alle Muscheln kompatibel

Neue Lösung:

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

Benchmark (in Datei speichern 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: [email protected]                      ##
##                             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

Ursprüngliche Lösung:

#!/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

^^^ Es hat sich gezeigt, dass die durchgestrichene Lösung die Dinge nicht beschleunigt, aber es gibt sie schon lange, also werde ich sie hier behalten, solange ich es für notwendig halte.


Erläuterung

Da das Lesen der $EUIDStandardvariablen bash, der effektiven Benutzer-ID-Nummer, um ein Vielfaches schneller ist als das Ausführen eines id -uBefehls zum POSIX- Finden der Benutzer-ID, kombiniert diese Lösung beides zu einer gut gepackten Funktion. Wenn und nur wenn der $EUIDaus irgendeinem Grund nicht verfügbar ist, wird der id -uBefehl ausgeführt, um sicherzustellen, dass wir unabhängig von den Umständen den richtigen Rückgabewert erhalten .


Warum ich diese Lösung nach so vielen Jahren poste, hat das OP gefragt

Nun, wenn ich richtig sehe, scheint oben ein fehlender Code zu fehlen.

Sie sehen, es gibt viele Variablen, die berücksichtigt werden müssen, und eine davon ist die Kombination von Leistung und Zuverlässigkeit .


Tragbare POSIX- Lösung + Beispiel für die Verwendung der oben genannten Funktion

#!/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

Fazit

So sehr es Ihnen auch nicht gefällt, die Unix / Linux-Umgebung hat sich stark verändert. Das heißt, es gibt Leute, die bashso sehr mögen , dass sie nicht einmal an Portabilität denken ( POSIX- Shells). Andere wie ich bevorzugen die POSIX- Shells. Es ist heutzutage eine Frage der persönlichen Wahl und der Bedürfnisse.

LinuxSecurityFreak
quelle
6

Wenn das Skript wirklich Root-Zugriff erfordert, sollten seine Dateiberechtigungen dies widerspiegeln. Ein Root-Skript, das von Nicht-Root-Benutzern ausgeführt werden kann, wäre eine rote Fahne. Ich ermutige Sie, den Zugang nicht mit einem ifScheck zu kontrollieren.

chown root:root script.sh
chmod u=rwx,go=r script.sh
John Kugelman
quelle
4
Wenn jemand seine Berechtigungen hat, damit dies gut funktioniert, aber ich glaube, dass eine übermäßige Verwendung der 777Bombe diese Überprüfung für die Art von Benutzern, die den Fehler überhaupt machen würden, ein wenig fehlerhaft macht.
Slater Victoroff
7
Dies setzt voraus, dass der Benutzer ein ausführbares Skript ausführt. Wenn der Benutzer nur anruft bash /path/to/script, kann es trotzdem ausgeführt werdeno=r
ptierno
5

Eine einfache Möglichkeit, das Skript nur für root ausführbar zu machen, besteht darin, das Skript mit der folgenden Zeile zu starten:

#!/bin/su root

alexandre1985
quelle
1
Ich bin gespannt, warum diese Antwort nicht höher gewählt wird. Es scheint das einfachste und sauberste zu sein. Gibt es hier Nachteile?
Bassinator
@Bassinator Ich glaube, einige Leute sagen, dass es auf bestimmten Nixen nicht läuft, aber auf meinem Linux funktioniert es bisher einwandfrei. Versuch es! Vielleicht ist diese Antwort zu spät zum Rennen gekommen, aber ich versuche, Wissen hinzuzufügen, das für die Community einfach ist (anstatt ähnliche Antworten zu geben, wie die meisten in diesem Thread: /) Stimmen Sie ab, wenn Sie das Glück haben, dies und das zu lesen arbeitet auf Ihrer Maschine
alexandre1985
@TamusJRoyce Wenn das Ziel darin besteht, zu überprüfen, ob Sie als Root ausgeführt werden und das Skript nicht gezwungen wird, nur als Root ausgeführt zu werden, warum wird dann in jeder Antwort nach der Überprüfung, ob es als Root ausgeführt wird, das Skript erstellt exit? Und immer noch werden diese Antworten positiv bewertet? Ich denke, die Leute wollen implizit nicht, dass das Skript als root ausgeführt wird. Ich folge dieser Denkweise mit einer einfacheren Antwort. Aber ja, Sie können auch aus den ausführlicheren Antworten oben lernen
alexandre1985
@ alexandre1985 Genau. Szenario: Wenn Sie als Root ausgeführt werden, möchten Sie möglicherweise, dass ein Skript das Programm standardmäßig global installiert, wenn Sie gefragt werden, wie es installiert werden soll. Andernfalls wird standardmäßig die lokale Installation festgelegt. Anstatt die Eingabetaste zu drücken, kann der Benutzer wählen, ob er global oder lokal installiert werden soll. Wenn ihnen die Standardeinstellung gefällt, können sie die Eingabetaste drücken. Und sie werden nicht mit einem Passwort aufgefordert. Ihr Shebang wird niemals "prüfen", ob Sie root sind (pro Titel). Aber ich denke immer noch, dass diese Antwort nützlich ist.
TamusJRoyce
@TamusJRoyce macht Ihren Kommentar absolut Sinn. In der Tat ist dies ein Problem, und diese Lösung ist nicht für diesen Anwendungsfall geeignet. Du hast meine Perspektiven geöffnet. Du hast recht. Danke
alexandre1985
4

Versuchen Sie den folgenden Code:

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

ODER

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

Soweit ich weiß, ist der richtige Weg, dies zu überprüfen ,:

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

Siehe Abschnitt "Testen auf Root" hier:

http://linuxcommand.org/lc3_wss0080.php

WebBrother
quelle
1
ersetzen = "0"durch-eq 0
LinuxSecurityFreak
1
@LinuxSecurityFreak, ich werde es ersetzen, wenn Sie erklären, warum ich es tun soll.
WebBrother
2

id -u ist viel besser als whoami , da einige Systeme wie Android möglicherweise nicht das Wort root liefern.

Beispiel:

# whoami
whoami
whoami: unknown uid 0
Smeterlink
quelle
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

Anmerkung des Herausgebers: Wenn Sie keine doppelten Klammern benötigen, verwenden Sie für die Code-Portabilität einzelne.

Pramod Kharade
quelle
3
Sie haben nicht erklärt, warum Sie eine alternative Antwort auf eine 5 Jahre alte Frage gegeben haben, auf die bereits mehrere Antworten vorliegen.
Styphon
0

Überprüfen Sie, ob Sie root sind, und beenden Sie, wenn Sie nicht:

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

Versuchen Sie in diesem Beispiel, ein Verzeichnis im Stammverzeichnis zu erstellen, und versuchen Sie es dann, nachdem die Rechte erhöht wurden.

Überprüfen Sie, ob Sie root sind und wenn nicht, wenn möglich:

# 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)
Mike Q.
quelle
-1

Auf root prüfen:

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

Getestet und läuft in root.

fvillalba89
quelle