Ich habe dieses Skript aus diesem Handbuch: www.tldp.org/LDP/abs/abs-guide.pdf
LOG_DIR=/var/log
ROOT_UID=0
LINES=50
E_XCD=86
E_NOTROOT=87
if [ "$UID" != "$ROOT_UID" ]
then
echo "Must be root to run this script."
exit $E_NOTROOT
fi
if [ -n "$1" ]
then
lines=$1
else
lines=$LINES
fi
cd $LOG_DIR
if [ 'pwd' != "$LOG_DIR" ]
then
echo "Can't change to $LOG_DIR."
exit $E_XCD
fi
Jetzt habe ich „sudo su“ im Terminal ausgeführt und $UID ausgegeben, was mir 0 gibt. Das bedeutet, dass meine if-Bedingung sich als falsch herausstellt, ich aber trotzdem die Meldung „Zum Ausführen dieses Skripts müssen Sie Root sein“ erhalte, während ich dieses Skript ausführe.
Auch im Originalskript wurde diese „if“-Bedingung wie folgt angegeben:
if [ "$UID" -ne "$ROOT_UID" ]
aber ich erhielt die Fehlermeldung „Ungültige Zahl“, weil -ne anscheinend nur für Zeichenfolgen verwendet wird, also habe ich es in != geändert.
Antwort1
Anstatt es auszuführen mit
sh script.sh
Führen Sie es aus mit
bash script.sh
#!/bin/bash
(oder als erste Zeile hinzufügen, um den Interpreter festzulegen).
Die sh
Shell in Ubuntu istnicht bash
, aber eine separate Shell namens dash
. dash
hat nicht so viele Funktionen wie bash
, was sie effizienter macht, aber diese fehlenden Funktionen beschädigen manchmal Skripte, die für gedacht sind bash
. Eine solche Funktion ist die $UID
Variable, dienicht definiertIn dash
.
Das bedeutet, dass der Vergleich bei Ausführung des Skripts in dash
zu führt ["" != "0"]
, was unabhängig vom Benutzer, der es ausführt, als wahr ausgewertet wird. Wenn es jedoch bash
mit Root-Berechtigungen ausgeführt wird, sind die Zeichenfolgen gleich und das Skript funktioniert.
Antwort2
AlsMcLovin sagt, die automatisch gesetzte, schreibgeschützte UID
(und EUID
) Variable ist eine Besonderheit vonbash
(und einige andere Shells). Es ist kein Standard fürShells im Bourne-Stilund sh
kann nicht davon ausgegangen werden, diese Variablen zu setzen. Insbesondere sh
in Ubuntu ist (derzeit standardmäßig)dash
, das sie nicht setzt.
Sie haben zwei Möglichkeiten:
bash
Bewirken Sie, dass Ihr Skript von statt von ausgeführt wirdsh
.- Ändern Sie Ihr Skript, damit es portabler ist und nicht erfordert
bash
.
Ausführen Ihres Skripts mitbash
Du hast uns den Namen deines Skripts nicht verraten (was in Ordnung ist). Ich werde es nennencleanup
, da dies der Name des ähnlichen Skripts in dem Handbuch ist, mit dem Sie arbeiten.
Beachten Sie insbesondere, dass ichnichtNennen Sie es etwa so cleanup.sh
. Das liegt daran, dass ich nicht empfehle, es mit einem .sh
Suffix zu benennen:
- Ein
.sh
Suffix weist auf die Kompatibilität mitsh
! hin. - Die meisten Skripte erhalten überhaupt kein Suffix, und ein Suffix
.sh
oder.bash
kann sogar so interpretiert werden, dass Ihre Datei eher eine „Bibliothek“ als ein „Top-Level“-Skript ist. Das heißt, dass es Code bereitstellt, der von anderen Skripten (z. B. mit dem.
integrierten) bezogen werden kann, anstatt tatsächlich direkt ausgeführt zu werden.
Das Einfügen eines Suffixes hat jedoch .sh
keinerlei Auswirkungen auf das technische Verhalten Ihres Skripts. Es sind damit weder technische Vor- noch Nachteile verbunden.
Füge hinzu einHashbang-Zeileals allererste Zeile Ihres Skripts:#!/bin/bash
Machen Sie Ihr Skript ausführbarmit .chmod +x cleanup
Jetzt kannst duFühren Sie Ihr Skript ausindem Sie den folgenden Befehl ausführen:
./cleanup
, wenn es sich im aktuellen Verzeichnis befindet. (Besonders beim Skripting für Bildungszwecke, Erkundung, Tests, Spaß oder andere begrenzte oder einmalige Verwendungszwecke ist dies wahrscheinlich die gebräuchlichste Methode.)/path/to/cleanup
, im Allgemeinen. Wenn das erste Wort eines Befehls ein enthält,/
wird es als Pfad zu einer ausführbaren Datei interpretiert. (Das ist der Grund für die obige./
Syntax, denn as.
bedeutet das aktuelle Verzeichnis.)Vonerstes WortIch meine den Befehl bis zum ersten Befehl, jedoch nicht einschließlichnicht entkommenLeerzeichen oder Tabulator:
foo-bar/baz
ist das erste Wort vonfoo-bar/baz qux
, währendspam\ ham
das erste Wort von ist,spam\ ham eggs
weil das Leerzeichen davorham
mit einem Backslash maskiert wird.cleanup
, wenn es sich in einem Verzeichnis in Ihrem befindetPATH
(und kein zuerst aufgeführtes Verzeichnis eine ausführbare Datei mit demselben Namen hat und diese nicht durch eineShell integriert,Funktion, oderalias).
Unabhängig davon, ob ein Skriptcleanup
hat eine #!...
Hashbang-Zeile oder was diese Zeile sagt:
sh cleanup
wird immer noch (versuchen), es mitsh
als Interpreter auszuführen.bash cleanup
wird immer noch (versuchen), es mitbash
als Interpreter auszuführen.
sh
Dies liegt daran, dass Sie in diesen Fällen tatsächlich den Interpreter ( oder ) ausführen bash
und den Namen des Skripts an den Interpreter übergeben, damit dieser es ausführen kann. Viele Programme akzeptieren Dateinamen, die auf der Befehlszeile geöffnet werden sollen, und Shells mögen sh
und bash
befolgen diese Konvention.
So machen Sie Ihr Skript portierbar
Wenn Sie Ihr Skript portierbar machen möchten, ist es am einfachsten, es $UID
überhaupt nicht zu verwenden und stattdessen eine Funktion zu nutzen, die allen Shells im Bourne-Stil zur Verfügung steht.
Im Allgemeinen gibt es keine integrierte Shell-Funktion zur Ermittlung der Benutzer-ID. Sie können jedoch verwendenid
. Dies ist ein externes Programm und kein Shell-Builtin, aber wiecat
Undls
, kann man davon ausgehen, dass es vorhanden sein wird.
id
gibt selbst eine Menge Informationen aus, id -u
gibt aber nur die tatsächliche Benutzer-ID an.
Anstelle von if [ "$UID" != "$ROOT_UID" ]
können Sie also Folgendes verwenden:
if [ "$(id -u)" != "$ROOT_UID" ]
Technisch, dies ist nicht gleichwertig. $UID
in bash
gibt die echte Benutzer-ID an und id -u
entspricht tatsächlich bash
's $EUID
. Wenn Sie wirklich die UID und nicht die EUID möchten, verwenden Sie id -ru
.