Ich habe ein Skript, das eine Reihe von verschiedenen Dingen ausführt, von denen die meisten keine besonderen Berechtigungen erfordern. Ein bestimmter Abschnitt, den ich in einer Funktion enthalten habe, benötigt jedoch Root-Rechte.
Ich möchte nicht, dass das gesamte Skript als Root ausgeführt wird, und ich möchte diese Funktion mit Root-Rechten innerhalb des Skripts aufrufen können. Wenn nötig nach einem Passwort zu fragen, ist kein Problem, da es sowieso meist interaktiv ist. Wenn ich versuche zu verwenden sudo functionx
, erhalte ich jedoch:
sudo: functionx: command not found
Wie ich erwartet hatte, export
machte das keinen Unterschied. Ich möchte in der Lage sein, die Funktion direkt im Skript auszuführen, anstatt sie aus verschiedenen Gründen aufzubrechen und als separates Skript auszuführen.
Gibt es eine Möglichkeit, meine Funktion für sudo "sichtbar" zu machen, ohne sie zu extrahieren, das entsprechende Verzeichnis zu finden und dann als eigenständiges Skript auszuführen?
Die Funktion ist ungefähr eine Seite lang und enthält mehrere Zeichenfolgen, einige in doppelten Anführungszeichen und einige in einfachen Anführungszeichen. Dies hängt auch von einer Menüfunktion ab, die an anderer Stelle im Hauptskript definiert ist.
Ich würde nur erwarten, dass jemand mit sudo ANY die Funktion ausführen kann, da eine der Aufgaben darin besteht, Kennwörter zu ändern.
declare
dieser Funktionen .Antworten:
Ich gebe zu, dass es keinen einfachen, intuitiven Weg gibt, und das ist ein bisschen kitschig. Aber du kannst es so machen:
Oder einfacher:
Für mich geht das:
Grundsätzlich
declare -f
wird der Inhalt der Funktion zurückgegeben, die Sie dannbash -c
inline übergeben.Wenn Sie alle Funktionen aus der äußeren Instanz von bash exportieren möchten, wechseln Sie
FUNC=$(declare -f hello)
zuFUNC=$(declare -f)
.Bearbeiten
Informationen zu den Kommentaren zum Zitieren finden Sie in diesem Beispiel:
quelle
echo "Hello!"
es praktisch dasselbe ist wieecho Hello!
(dh doppelte Anführungszeichen machen für diesen speziellen Echobefehl keinen Unterschied). In vielen / den meisten anderen Fällen wird derbash -c
Befehl wahrscheinlich durch doppelte Anführungszeichen in der Funktion unterbrochen.bash -xc
und nicht nurbash -c
), und es scheintbash
klug genug zu sein, Dinge in dieser Situation erneut zu zitieren, selbst in dem Maße, in dem doppelte Anführungszeichen durch einfache Anführungszeichen ersetzt und bei Bedarf'
auf'\''
geändert werden. Ich bin mir sicher, dass es einige Fälle geben wird, die nicht behandelt werden können, aber es funktioniert definitiv für zumindest einfache und mäßig komplexe Fälle - zB tryfunction hello() { filename="this is a 'filename' with single quotes and spaces" ; echo "$filename" ; } ; FUNC=$(declare -f hello) ; bash -xc "$FUNC ; hello"
declare -f
die Funktionsdefinition auf eine Weise aus, die von bash erneut analysiert werden kann. Dies funktioniertbash -c "$(declare -f)"
also ordnungsgemäß (vorausgesetzt, die äußere Shell ist ebenfalls bash). Das Beispiel, das Sie gepostet haben, zeigt, dass es korrekt funktioniert - wo die Anführungszeichen geändert wurden, befindet sich im Trace , da Bash Spuren in Shell-Syntax ausgibt, z. B. trybash -xc 'echo "hello world"'
sudo yourFunction
gefunden werden (Sie sonst einen Segmentierungsfehler aus der Rekursion erhalten)Das "Problem" besteht darin, dass
sudo
die Umgebung gelöscht wird (mit Ausnahme einiger zulässiger Variablen) und einige Variablen auf vordefinierte sichere Werte gesetzt werden, um sich vor Sicherheitsrisiken zu schützen. Mit anderen Worten, dies ist eigentlich kein Problem. Es ist ein Feature.Wenn Sie beispielsweise PATH auf einen vordefinierten Wert setzen
PATH="/path/to/myevildirectory:$PATH"
undsudo
nicht setzen, sucht jedes Skript, das nicht den vollständigen Pfadnamen für ALLE von ihm ausgeführten Befehle angibt (dh die meisten Skripte),/path/to/myevildirectory
vor jedem anderen Verzeichnis. Wenn Sie Befehle wiels
odergrep
andere gebräuchliche Tools einfügen, können Sie auf einfache Weise das tun, was Sie möchten.Der einfachste / beste Weg ist, die Funktion als Skript neu zu schreiben und irgendwo im Pfad zu speichern (oder den vollständigen Pfad zum Skript in der
sudo
Befehlszeile anzugeben - was Sie sowieso tun müssen, es sei denn, diessudo
ist so konfiguriert, dass Sie dies zulassen JEDEN Befehl als root ausführen) und mit ausführbar machenchmod +x /path/to/scriptname.sh
Das Umschreiben einer Shell-Funktion als Skript ist so einfach wie das Speichern der Befehle in der Funktionsdefinition in eine Datei (ohne die Zeilen
function ...
,{
und}
).quelle
sudo -E
Vermeidet auch das Räumen der Umgebung.Ich habe dazu meine eigene
Sudo
Bash-Funktion geschrieben, die Funktionen und Aliase aufruft:quelle
Sie können Funktionen und Aliase kombinieren
Beispiel:
dann
sudo hello
klappt esquelle
Hier ist eine Variation von Wills Antwort . Es beinhaltet einen zusätzlichen
cat
Prozess, bietet aber den Komfort von heredoc. Kurz gesagt, es geht so:Wenn Sie mehr zum Nachdenken anregen möchten, versuchen Sie Folgendes:
Die Ausgabe ist:
Hier haben wir die
menu
Funktion, die der in der Frage entspricht, die "an anderer Stelle im Hauptskript definiert ist". Wenn das "anderswo" bedeutet, dass seine Definition bereits zu diesem Zeitpunkt gelesen wurde, als die Funktion "forderndsudo
" ausgeführt wird, ist die Situation analog. Aber es könnte noch nicht gelesen worden sein. Möglicherweise gibt es eine andere Funktion, die ihre Definition noch auslöst. In diesem Falldeclare -f menu
muss es durch etwas Raffinierteres ersetzt oder das gesamte Skript so korrigiert werden, dass diemenu
Funktion bereits deklariert ist.quelle
menu
Funktion wäre vor diesem Punkt deklariert worden, wief
es aus einem Menü aufgerufen wird.Angenommen, Ihr Skript ist entweder (a) eigenständig oder (b) kann seine Komponenten basierend auf seinem Speicherort beziehen (anstatt sich zu erinnern, wo sich Ihr Ausgangsverzeichnis befindet), können Sie Folgendes tun:
$0
Pfadnamen für das Skriptsudo
und geben Sie eine Option ein, die vom Skript überprüft wird, um die Kennwortaktualisierung aufzurufen. Solange Sie darauf angewiesen sind, das Skript im Pfad zu finden (und nicht nur auszuführen./myscript
), sollten Sie einen absoluten Pfadnamen in erhalten$0
.sudo
Skript ausgeführt wird, hat es Zugriff auf die Funktionen, die es im Skript benötigt.uid
, ob es als Root- Benutzer ausgeführt wurde, und stellt fest, dass die Option festgelegt ist, dass das Kennwort aktualisiert werden soll Das.Skripte können sich aus verschiedenen Gründen wiederholen: Das Ändern von Berechtigungen ist eine davon.
quelle