So stoppen Sie die Ausführung eines Skripts, wenn es nicht als Root ausgeführt wird

17

Hier ist meine Quelle:

#!/bin/bash

echo "Running script to free general cached memory!"
echo "";
echo "Script must be run as root!";
echo "";
echo "Clearing swap!";
swapoff -a && swapon -a;
echo "";
echo "Clear inodes and page file!";
echo 1 > /proc/sys/vm/drop_caches;
echo "";

Es löscht Caches und andere Daten und gibt an, dass es als Root im Terminal ausgeführt werden muss. Ich möchte im Grunde nur, dass das Skript nicht mehr ausgeführt wird, wenn es feststellt, dass es nicht als root ausgeführt wird.

Beispiel:

"Running script to free general cached memory!"
"Warning: script must be run as root or with elevated privileges!"
"Error: script not running as root or with sudo! Exiting..."

Wenn es mit erhöhten Rechten ausgeführt wird, wird es wie gewohnt ausgeführt. Irgendwelche Ideen? Vielen Dank!

M. Knepper
quelle
Mögliches Duplikat von Wie man root daran hindert, ein Skript
auszuführen
2
@muru, mit der Ausnahme, dass die andere Frage das Gegenteil ist: Schlage das Skript fehl, wenn es als root ausgeführt wird.
Stéphane Chazelas
3
@ StéphaneChazelas ah, mein schlechtes. Zurückgezogen
muru
Eine Alternative ist es, die Menge der Arbeit , wie ausgeführt zu begrenzen rootdurch Vorfixierung prefix alle Befehle , die ausgeführt werden müssen , wie rootmit sudo.
Reinierpost

Antworten:

46
#!/bin/sh

if [ "$(id -u)" -ne 0 ]; then
        echo 'This script must be run by root' >&2
        exit 1
fi

cat <<HEADER
Host:          $(hostname)
Time at start: $(date)

Running cache maintenance...
HEADER

swapoff -a && swapon -a
echo 1 >/proc/sys/vm/drop_caches

cat <<FOOTER
Cache maintenance done.
Time at end:   $(date)
FOOTER

Der Root-Benutzer hat die UID 0 (unabhängig vom Namen des "Root" -Kontos). Wenn die von zurückgegebene effektive UID id -unicht Null ist, führt der Benutzer das Skript nicht mit Root-Rechten aus. Verwenden Sie id -ruzum Test gegen die reale ID (die UID des Benutzers Aufruf des Skripts).

Nicht $EUIDim Skript verwenden, da dies von einem nicht privilegierten Benutzer geändert werden kann:

$ bash -c 'echo $EUID'
1000

$ EUID=0 bash -c 'echo $EUID'
0

Wenn ein Benutzer dies tun würde, würde dies offensichtlich nicht zu einer Eskalation der Rechte führen, sondern könnte dazu führen, dass Befehle im Skript nicht in der Lage sind, das zu tun, was sie tun sollen, und dass Dateien mit dem falschen Eigentümer erstellt werden usw.

Kusalananda
quelle
1
Hinweis: Unter Solaris 5.10 /bin/id -ugibt es/bin/id: illegal option -- u Usage: id [-ap] [user]
jrw32982 unterstützt Monica
1
@ jrw32982 Sie sollten /usr/xpg4/binfrühzeitig $PATHZugriff auf POSIX-Dienstprogramme unter Solaris haben.
Kusalananda
1
Der Punkt ist, dass die -uOption von idnicht universell ist und daher diese Lösung nur mit dem Vorbehalt universell ist, dass eine POSIX-Version von idzuerst in Ihrem PATH auftreten muss.
jrw32982 unterstützt Monica
1
@ jrw32982 Wenn Sie möchten, dass Ihr Skript die richtigen POSIX-Dienstprogramme unter Solaris aufruft, ändern Sie diese $PATHoben im Skript so, dass sie /usr/xpg4/binzuvor angezeigt wurden /bin. Wenn Sie darauf bestehen, Nicht-POSIX zu verwenden id, müssen Sie natürlich eine tragbarere Lösung finden.
Kusalananda
1
@Harry Ja, daher könnte das Skript PATH=$( getconf PATH )einen anderen expliziten Standardpfad verwenden oder festlegen oder einen expliziten Pfad zum Aufrufen verwenden id.
Kusalananda
19

Ich denke, was Sie wollen, ist eher zu überprüfen, ob Sie Super-User-Berechtigungen haben, das heißt, dass Ihre effektive Benutzer-ID 0 ist.

zshund bashstellen $EUIDSie dies in der Variablen zur Verfügung, damit Sie Folgendes tun können:

if ((EUID != 0)); then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

Mit allen POSIX-ähnlichen Shells können Sie den idStandardbefehl verwenden:

if [ "$(id -u)" -ne 0 ]; then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

Beachten Sie, dass alle id -unoder whoamioder die $USERNAMEVariable in zshIhnen den ersten Benutzernamen für die UID erhalten. Auf Systemen mit anderen Benutzern mit der ID 0 ist dies möglicherweise nicht der Fall, rootauch wenn der Prozess ein Nachkomme eines Prozesses ist, der als authentifiziert wurde root.

$USERwürde Ihnen normalerweise den Benutzer geben, der sich authentifiziert, aber sich darauf zu verlassen, ist ziemlich spröde. Es ist nicht von dem Shell gesetzt, sondern wird in der Regel durch den authentifizierten Befehl (wie festgelegt login, su(auf GNU / Linux - Systeme, die nicht unbedingt andere) sudo, sshd(der einer von OpenSSH zumindest) ...). Dies ist jedoch nicht immer der Fall (das Ändern der UID setzt diese Variable nicht automatisch, sondern muss explizit von der Anwendung vorgenommen werden, die die UID ändert) und könnte auch durch einen anderen Prozess in der Vorfahren der Shell geändert worden sein. $LOGNAME, mit dem gleichen Vorbehalt ist zuverlässiger als es von POSIX angegeben wird (ursprünglich von FIPS 151-2)

Stéphane Chazelas
quelle
12

Mit $USERoder whoamikönnen Sie den aktuellen Benutzer überprüfen.

if [[ "$USER" != "root" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi

if [[ $(whoami) != "root" ]]; then
    echo "Warning: script must be run as root or with elevated privileges!"
    exit 1
fi

if [[ $(id -u) != "0" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi
Jesse_b
quelle
1
NP. Ich schlage vor, nur das Bash-Handbuch durchzulesen [ gnu.org/software/bash/manual/bashref.html] . Es ist eigentlich überraschend einfach fertig. Insbesondere für diese Antwort schlage ich vor, auf 3.2.4.2 Conditional Constructs 3.5.4 Command Substitution
Folgendes zu
9
Der Befehl id -umit oder ohne -nOption ist eine Alternative zur Verwendung von whoami. Ohne ein -n und einen Vergleich mit Null ist eine bessere Übereinstimmung mit dem Test, den der Kernel tatsächlich durchführt. Der Kernel kümmert sich nur um die ID und nicht um den Namen aus der Passwortdatei.
Ikarus
6
Ich glaube, dass das Verwenden $(id -u)besser ist. In einigen (böswilligen) Fällen $USERkönnte das falsch sein.
Basile Starynkevitch
1
Für diejenigen, die an dem von @Jesse_b bereitgestellten Link interessiert sind: Es gibt einen Tippfehler. Es sollte gnu.org/software/bash/manual/bashref.html
Kryten
1
Einige Systeme verwenden nicht "root" als Namen des privilegierten Kontos mit der UID 0. QNAP wird als einer bezeichnet. Sie sollten also nur die UID 0 und nicht den Namen des Root-Kontos überprüfen.
Roaima
10

Was Sie tatsächlich wollen, ist festzustellen, ob Sie Zugriff auf diese Vorgänge haben. Es wird als schlechte Praxis angesehen, stattdessen zu prüfen, ob Sie Root sind oder nicht.

Wenn das System so konfiguriert wurde, dass ein Benutzer ohne Rootberechtigung den Swap- und Drop-Page-Cache ändern kann, warum sollte dieser Benutzer dann nicht das Skript ausführen können?

Stattdessen können Sie die Operation einfach ausprobieren und mit einer hilfreichen Meldung beenden, falls dies fehlschlägt:

if ! ( swapoff -a && swapon -a )
then
  echo "Failed to clear swap (rerun as root?)" >&2
  exit 1
fi

if ! echo 1 > /proc/sys/vm/drop_caches
then 
  echo "Failed to free page cache (rerun as root?)" >&2
  exit 1
fi
dieser andere Typ
quelle
Ein Benutzer ohne Rootberechtigung, der Swap ausschaltet?
Kusalananda
2
Ja. Sie können dies mit SELinux einrichten. Ebenso können Sie einen Root-Prozess daran hindern, dies zu tun.
andere
1
Möglicherweise möchten Sie nicht, exitnachdem etwas fehlgeschlagen ist, falls der Benutzer mit seinen aktuellen Berechtigungen so viel wie möglich tun möchte. (Aber für ein typisches System, bei dem dies alles root erfordert, wäre das Beenden nützlicher / weniger laut.)
Peter Cordes
2
Ich würde nicht sagen, dass es "schlechte Praxis" ist, zu überprüfen, ob Sie root sind oder nicht. Vor allem, wenn Sie genau das wissen wollen. Ich gehe davon aus, dass es am besten ist, zu überprüfen, ob Sie über ausreichende Berechtigungen verfügen, um das zu tun, was Sie möchten.
Erik Bennett