Come mantenere le variabili di ambiente quando si usa sudo


425

Quando uso qualsiasi comando con sudo le variabili di ambiente non ci sono. Ad esempio, dopo aver impostato HTTP_PROXY, il comando wgetfunziona senza sudo. Tuttavia, se digito sudo wget, dice che non può ignorare l'impostazione del proxy.



Risposte:


475

Per prima cosa devi export HTTP_PROXY. In secondo luogo, è necessario leggere man sudoattentamente e prestare attenzione alla -Ebandiera. Questo funziona:

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

Ecco la citazione dalla pagina man:

-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
ottimo l'unico problema che è modificare alcuni file di configurazione come pacman per arch per far passare -E
Ahmed Aswani il

7
Per consentire -E (preservare l'ambiente) per wget, è necessario specificare il tag SETENV sulla regola sudo che consente l'esecuzione di wget - Esempio: <username> ALL = (root) NOPASSWD: SETENV: <percorso da wget>
John Bowers,

66
Questo "-E" non funziona se la variabile è PATH o PYTHONPATH.
Apporc,

Inoltre non funziona con nessuna LC_*variabile. Quindi basta fare export LOL_FOO=$LC_FOOe usare LOL_FOOinvece.
luckydonald

9
Questo non ha funzionato con il caso più semplice di aggiungere un elemento al PATHnel .bashrcfile di - per esempio, export PATH=myPath:$PATH. Se scriv sudo -E bash -c 'echo $PATH', quindi PATHnon contiene myPath probabilmente perché sudoha già disattivato il valore locale di PATHprima di chiamare bash. Piuttosto, ho trovato la risposta sotto stackoverflow.com/a/33183620/5459638 efficace, cioèsudo PATH=$PATH command
XavierStuvw

310

Il trucco è aggiungere variabili di ambiente al sudoersfile tramite sudo visudocomando e aggiungere queste righe:

Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"

tratto dal wiki di ArchLinux .

Per Ubuntu 14, è necessario specificare in righe separate poiché restituisce gli errori per le righe multi-variabile:

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

11
Questa è probabilmente l'opzione migliore, per evitare perdite di informazioni e falle di sicurezza. sudo -Eè il modo sicuro per ottenere lo stesso effetto per una tantum, però
vedere il

Ho riscontrato il problema di un processo che è quello che chiama sudo (jhbuild) e non posso dirgli di passare il flag -E a sudo, quindi questa è la mia soluzione.
jgomo3,

61
Si noti che non si dovrebbe mai modificare etc/sudoersdirettamente. Utilizzare invece il visudocomando, che controlla la sintassi delle modifiche prima di sovrascrivere il sudoersfile. In questo modo, non ti blocchi se commetti un errore durante la modifica.
Henning,

1
Prendi in considerazione l'uso di lettere maiuscole env. Nel mio caso l'uso di HTTP_PROXY e HTTPS_PROXY ha funzionato.
pabo,

2
la variante minuscola è migliore dalla mia esperienza in quanto funziona sia in wget che in curl.
Miroslav Mocek,

57

Per le singole variabili che si desidera rendere disponibili una tantum, è possibile renderlo parte del comando.

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

Ho testato questa risposta per un packagesotto qualche myPath aggiunto PATHnel .bashrcfile (con exportclausule). Quindi sudo PATH=$PATH which packagetrova la risposta giusta, a differenza sudo which package. Tuttavia, sudo PATH=$PATH packagenon va oltre sudo package(file non trovato). D'altra parte, il lancio di una pianura packageda una shell invocata con sudo bashconserva il percorso esteso e conferisce i packagediritti di sudo (due piccioni con una fava). Quindi la risposta dipende davvero da quali comandi stai lanciando
XavierStuvw il

2
La risoluzione del PERCORSO per sudo è un'altra questione: se qualcuno dovesse trovare questo post alla ricerca di quella questione, suggerisco di vedere unix.stackexchange.com/questions/83191/…
buckaroo1177125

24

Puoi anche combinare le due env_keepaffermazioni nella risposta di Ahmed Aswani in un'unica affermazione come questa:

Defaults env_keep += "http_proxy https_proxy"

Dovresti anche considerare di specificare env_keepun solo comando come questo:

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


1

Una semplice funzione wrapper (o in-line per loop)

Ho trovato una soluzione unica perché:

  • sudo -E "$@" perdeva variabili che causavano problemi al mio comando
  • sudo VAR1="$VAR1" ... VAR42="$VAR42" "$@" era lungo e brutto nel mio caso

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

Risultato

$ ./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.

Come?

Ciò è reso possibile da una funzione del built-in bash printf. Il %qproduce una stringa tra virgolette shell. A differenza dell'espansione dei parametri in bash 4.4 , questo funziona nelle versioni bash <4.0


0

Se hai la necessità di mantenere le variabili di ambiente in uno script puoi inserire il tuo comando in un documento qui come questo. Soprattutto se hai molte variabili per sistemare le cose in questo modo.

# 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.