Antworten:
sudo su -
, eine komplizierte Schreibweise sudo -i
, schafft eine makellose Umgebung. Das ist der Punkt einer Login-Shell. Sogar eine Ebene sudo
entfernt die meisten Variablen aus der Umgebung. Weiterhin sudo
ist ein externer Befehl; Es gibt keine Möglichkeit, Berechtigungen im Shell-Skript selbst zu erhöhen, sondern nur ein externes Programm ( sudo
) mit zusätzlichen Berechtigungen auszuführen. Dies bedeutet, dass in der übergeordneten Shell definierte Shell-Variablen (dh nicht exportierte Variablen) und Funktionen nicht verfügbar sind die Kinderhülle.
Sie können Umgebungsvariablen weitergeben, indem Sie keine Anmeldeshell ( sudo bash
anstelle von sudo su -
oder sudo -i
) aufrufen und sudo so konfigurieren, dass diese Variablen (mit Defaults !env_reset
oder Defaults env_keep=…
in der sudoers
Datei) durchgelassen werden. Dies hilft Ihnen bei Funktionen nicht weiter (obwohl bash über eine Funktion zum Exportieren von Funktionen verfügt, blockiert sudo diese).
Der normale Weg, um Ihre Funktionen in die untergeordnete Shell zu bekommen, besteht darin, sie dort zu definieren. Achten Sie <<EOF
auf das Zitieren: Wenn Sie für das Here-Dokument verwenden, wird der Inhalt des Here-Dokuments zuerst von der übergeordneten Shell erweitert, und das Ergebnis dieser Erweiterung wird zum Skript, das die untergeordnete Shell sieht. Das heißt, wenn Sie schreiben
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
Dies zeigt den Namen des ursprünglichen Benutzers an, nicht des Zielbenutzers. Um diese erste Phase der Erweiterung zu vermeiden, zitieren Sie die hier angegebene Dokumentmarkierung nach dem <<
Operator:
sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF
Wenn Sie also keine Daten von der übergeordneten Shell an die untergeordnete Shell übergeben müssen, können Sie ein hier zitiertes Dokument verwenden:
#!/bin/bash
sudo -u "$target_user" -i <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF
Während Sie eine hier nicht zitierte Dokumentmarkierung verwenden können, um Daten von der übergeordneten Shell an die untergeordnete Shell zu übergeben, funktioniert dies nur, wenn die Daten kein Sonderzeichen enthalten. Das liegt daran, dass in einem Skript wie
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
Die Ausgabe von whoami
wird zu einem Bit Shell-Code, nicht zu einer Zeichenfolge. Wenn der whoami
Befehl beispielsweise zurückgegeben "; rm -rf /; "true
wird, führt die untergeordnete Shell den Befehl aus echo ""; rm -rf /; "true"
.
Wenn Sie Daten von der übergeordneten Shell übergeben müssen, können Sie sie auf einfache Weise als Argumente übergeben. Rufen Sie die untergeordnete Shell explizit auf und übergeben Sie die Positionsparameter:
#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i sh _ "$extVAR" <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}" "${1}"
EOF
Wenn Sie mehrere Variablen übergeben müssen, ist es besser, sie nach Namen zu übergeben. Rufen Sie env
explizit auf, um Umgebungsvariablen für die untergeordnete Shell festzulegen.
#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i env extVAR="$extVAR" sh <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}" "${1}"
EOF
Beachten Sie, dass Sie, wenn Sie erwartet haben /etc/profile
und der Zielbenutzer ~/.profile
gelesen werden soll, diese explizit lesen oder bash --login
stattdessen aufrufen müssen sh
.
Dies funktioniert nicht, da die Funktion log_f
in der von sudo su -
Ihnen gestarteten Shell nicht deklariert ist . Stattdessen:
extVAR="yourName"
sudo su - <user> << EOF
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f ${intVAR} ${extVAR}
EOF
Sie müssen die in der Root-Subshell definierte Funktion erhalten. Das könnte es tun, aber ... ich weiß nicht, was das meiste davon macht. Zumindest - solange weder stdin sudo
noch su
stdin zum Lesen eines Passworts benötigt wird - sollte dies log_f()
deklariert werden.
Ich vertraue darauf, dass Sie diese Werte übrigens in die Eingabe der Root-Shell erweitern wollen. Wenn Sie dies nicht beabsichtigen, sollten Sie EOF
und die Vars selbst zitieren .
In meinem Fall musste ich ein Array übergeben und hatte einige Probleme, hatte aber nach einer Weile Erfolg, indem env
ich die Werte des Arrays auf einen -key wiederholte und den beabsichtigten Code einwickelte bash -c '<intended code>'
und es im Grunde das Array neu erstellen ließ , z INNER_KEY=($<env_key>)
.
Zum Beispiel:
#!/usr/bin/env bash
PLUGINS=(foo bar baz)
sudo -u <some-user> -i env PLUGINS="`echo ${PLUGINS[@]}`" sh <<'EOF'
bash -c '
FOO=($PLUGINS);
echo values: \[${FOO[@]}\];
for pl in ${FOO[@]};
do echo value: $pl;
done;
'
EOF
Das Problem war, dass ich so etwas nicht direkt tun konnte (nicht verwenden bash -c '...'
):
FOO=($PLUGINS);
for pl in ${FOO[@]};
...