So behalten Sie Umgebungsvariablen bei, wenn Sie sudo verwenden


425

Wenn ich einen Befehl mit sudo verwende, sind die Umgebungsvariablen nicht vorhanden. Zum Beispiel funktioniert der Befehl nach dem Setzen von HTTP_PROXY wgetohne sudo. Wenn ich jedoch tippe sudo wget, heißt es, dass die Proxy-Einstellung nicht umgangen werden kann.



Antworten:


475

Zuerst musst du export HTTP_PROXY. Zweitens müssen Sie man sudosorgfältig lesen und auf die -EFlagge achten . Das funktioniert:

$ export HTTP_PROXY=foof
$ sudo -E bash -c 'echo $HTTP_PROXY'

Hier ist das Zitat aus der Manpage:

-E, --preserve-env
             Indicates to the security policy that the user wishes to preserve their
             existing environment variables.  The security policy may return an error
             if the user does not have permission to preserve the environment.

1
Großartig, das einzige Problem, das darin besteht, einige Konfigurationsdateien zu ändern, zum Beispiel pacman for arch, um das -E zu erstellen, ist übergeben
Ahmed Aswani

7
Um -E (Umgebung beibehalten) für wget zuzulassen, müssen Sie das SETENV-Tag in der sudo-Regel angeben, mit der wget ausgeführt werden kann. Beispiel: <Benutzername> ALL = (root) NOPASSWD: SETENV: <Pfad zu wget>
John Bowers

65
Dieses "-E" funktioniert nicht, wenn die Variable PATH oder PYTHONPATH ist.
Apporc

Funktioniert auch nicht mit einer LC_*Variablen. Also einfach tun export LOL_FOO=$LC_FOOund LOL_FOOstattdessen verwenden.
Luckydonald

9
Das ist nicht mit dem einfacheren Fall arbeitete ein Element die Zugabe PATHin der .bashrcDatei -, sagen sie export PATH=myPath:$PATH. Wenn ich schreibe sudo -E bash -c 'echo $PATH', dann PATHenthält keine myPath wahrscheinlich , weil sudobereits den lokalen Wert deaktiviert PATHvor dem Aufruf bash. Vielmehr fand ich die Antwort unter stackoverflow.com/a/33183620/5459638 effektiv, das heißtsudo PATH=$PATH command
XavierStuvw

310

Der Trick besteht darin, Umgebungsvariablen sudoersper sudo visudoBefehl zur Datei hinzuzufügen und folgende Zeilen hinzuzufügen:

Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"

entnommen aus dem ArchLinux-Wiki .

Für Ubuntu 14 müssen Sie in separaten Zeilen angeben, da die Fehler für Zeilen mit mehreren Variablen zurückgegeben werden:

Defaults  env_keep += "http_proxy"
Defaults  env_keep += "https_proxy"
Defaults  env_keep += "HTTP_PROXY"
Defaults  env_keep += "HTTPS_PROXY"

11
Dies ist wohl die beste Option, um Informationslecks und Sicherheitslücken zu vermeiden. sudo -Eist der sichere Weg, um Ad-hoc den gleichen Effekt für ein einmaliges Ergebnis zu erzielen
siehe

Ich bin auf das Problem gestoßen, dass ein Prozess derjenige ist, der sudo (jhbuild) aufruft, und ich kann ihm nicht sagen, dass er das Flag -E an sudo übergeben soll. Dies ist also meine Lösung.
jgomo3

60
Beachten Sie, dass Sie das niemalsetc/sudoers direkt bearbeiten sollten . Verwenden Sie stattdessen den visudoBefehl, der Ihre Änderungen syntaktisch überprüft, bevor Sie die sudoersDatei überschreiben . Auf diese Weise sperren Sie sich nicht aus, wenn Sie beim Bearbeiten einen Fehler machen.
Henning

1
Erwägen Sie die Verwendung von env vars in Großbuchstaben. In meinem Fall hat die Verwendung von HTTP_PROXY und HTTPS_PROXY den Trick getan.
Pabo

2
Kleinbuchstabenvariante ist meiner Erfahrung nach besser, da sie sowohl in Wget als auch in Curl funktioniert.
Miroslav Mocek

57

Für einzelne Variablen, die Sie einmalig verfügbar machen möchten, können Sie sie Teil des Befehls machen.

sudo http_proxy=$http_proxy wget "http://stackoverflow.com"

Ich habe diese Antwort auf einen packageunter myPath getestet , der PATHin der .bashrcDatei hinzugefügt wurde (mit exportKlausel). Dann sudo PATH=$PATH which packagefindet er im Gegensatz dazu die richtige Antwort sudo which package. Allerdings sudo PATH=$PATH packagegeht nicht weiter als sudo package(Datei nicht gefunden). Auf der anderen Seite bewahrt das Starten einer Ebene packageaus einer mit aufgerufenen Muschel sudo bashden erweiterten Pfad und gibt packageSudo-Rechte (zwei Tauben mit einer Klappe). Die Antwort hängt also wirklich davon ab, welche Befehle Sie starten
XavierStuvw

2
PATH Auflösung für Sudo ist eine andere Sache - sollte jemand diesen Beitrag auf der Suche nach dieser Angelegenheit finden, schlage
buckaroo1177125

24

Sie können die beiden env_keepAussagen in Ahmed Aswanis Antwort auch zu einer einzigen Aussage wie dieser kombinieren :

Defaults env_keep += "http_proxy https_proxy"

Sie sollten auch in Betracht ziehen, env_keepnur einen einzigen Befehl wie diesen anzugeben :

Defaults!/bin/[your_command] env_keep += "http_proxy https_proxy"


1

Eine einfache Wrapper-Funktion (oder eine Inline-for-Schleife)

Ich habe eine einzigartige Lösung gefunden, weil:

  • sudo -E "$@" Es gab Variablen, die Probleme für meinen Befehl verursachten
  • sudo VAR1="$VAR1" ... VAR42="$VAR42" "$@" war lang und hässlich in meinem Fall

demo.sh

#!/bin/bash

function sudo_exports(){
    eval sudo $(for x in $_EXPORTS; do printf '%q=%q ' "$x" "${!x}"; done;) "$@"
}

# create a test script to call as sudo
echo 'echo Forty-Two is $VAR42' > sudo_test.sh
chmod +x sudo_test.sh

export VAR42="The Answer to the Ultimate Question of Life, The Universe, and Everything."

export _EXPORTS="_EXPORTS VAR1 VAR2 VAR3 VAR4 VAR5 VAR6 VAR7 VAR8 VAR9 VAR10 VAR11 VAR12 VAR13 VAR14 VAR15 VAR16 VAR17 VAR18 VAR19 VAR20 VAR21 VAR22 VAR23 VAR24 VAR25 VAR26 VAR27 VAR28 VAR29 VAR30 VAR31 VAR32 VAR33 VAR34 VAR35 VAR36 VAR37 VAR38 VAR39 VAR40 VAR41 VAR42"

# clean function style
sudo_exports ./sudo_test.sh

# or just use the content of the function
eval sudo $(for x in $_EXPORTS; do printf '%q=%q ' "$x" "${!x}"; done;) ./sudo_test.sh

Ergebnis

$ ./demo.sh
Forty-Two is The Answer to the Ultimate Question of Life, The Universe, and Everything.
Forty-Two is The Answer to the Ultimate Question of Life, The Universe, and Everything.

Wie?

Dies wird durch eine Funktion der eingebauten Bash ermöglicht printf. Das %qerzeugt eine Shell-Zeichenfolge in Anführungszeichen. Im Gegensatz zur Parametererweiterung in Bash 4.4 funktioniert dies in Bash-Versionen <4.0


0

Wenn Sie die Umgebungsvariablen in einem Skript behalten müssen, können Sie Ihren Befehl in ein solches Dokument einfügen. Besonders wenn Sie viele Variablen haben, um die Dinge auf diese Weise ordentlich einzustellen.

# prepare a script e.g. for running maven
runmaven=/tmp/runmaven$$
# create the script with a here document 
cat << EOF > $runmaven
#!/bin/bash
# run the maven clean with environment variables set
export ANT_HOME=/usr/share/ant
export MAKEFLAGS=-j4
mvn clean install
EOF
# make the script executable
chmod +x $runmaven
# run it
sudo $runmaven
# remove it or comment out to keep
rm $runmaven
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.