Comment conserver les variables d'environnement lors de l'utilisation de sudo


425

Lorsque j'utilise une commande avec sudo, les variables d'environnement ne sont pas là. Par exemple, après avoir défini HTTP_PROXY, la commande wgetfonctionne correctement sans sudo. Cependant, si je tape, sudo wgetil dit qu'il ne peut pas contourner le paramètre proxy.



Réponses:


475

Vous devez d'abord export HTTP_PROXY. Deuxièmement, vous devez lire man sudoattentivement et faire attention au -Edrapeau. Cela marche:

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

Voici la citation de la page de manuel:

-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
grand le seul problème qui est de modifier certains fichiers de configuration par exemple pacman pour arch pour faire le -E est passé
Ahmed Aswani

7
Pour autoriser -E (préserver l'environnement) pour wget, vous devez spécifier la balise SETENV sur la règle sudo qui permet l'exécution de wget - Exemple: <nom d'utilisateur> ALL = (racine) NOPASSWD: SETENV: <chemin vers wget>
John Bowers

66
Ce "-E" ne fonctionne pas si la variable est PATH ou PYTHONPATH.
Apporc

Ne fonctionne également avec aucune LC_*variable. Il suffit donc de faire export LOL_FOO=$LC_FOOet d'utiliser à la LOL_FOOplace.
luckydonald

9
Cela ne fonctionne pas avec le cas plus simple d'ajouter un élément au PATHdans le .bashrcfichier - par exemple, export PATH=myPath:$PATH. Si je tape sudo -E bash -c 'echo $PATH', alors PATHne contient probablement pas myPath car sudoa déjà désactivé la valeur locale de PATHavant d'appeler bash. Au contraire, je trouve la réponse ci - dessous stackoverflow.com/a/33183620/5459638 efficace, qui estsudo PATH=$PATH command
XavierStuvw

310

L'astuce consiste à ajouter des variables d'environnement au sudoersfichier via la sudo visudocommande et à ajouter ces lignes:

Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"

extrait du wiki ArchLinux .

Pour Ubuntu 14, vous devez spécifier sur des lignes distinctes car il renvoie les erreurs pour les lignes multi-variables:

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

11
C'est sans doute la meilleure option pour éviter les fuites d'informations et les failles de sécurité. sudo -Eest le moyen infaillible pour adhoc obtenir le même effet pour une unique, mais
sehe

J'ai rencontré le problème d'un processus étant celui qui appelle sudo (jhbuild) et je ne peux pas lui dire de passer l'indicateur -E à sudo, c'est donc ma solution.
jgomo3

61
Notez que vous ne devez jamais modifier le etc/sudoersdirectement. Utilisez plutôt la visudocommande qui vérifie la syntaxe de vos modifications avant d'écraser le sudoersfichier. De cette façon, vous ne vous verrouillez pas si vous faites une erreur lors de l'édition.
Henning

1
Envisagez d'utiliser des vars env majuscules. Dans mon cas, l'utilisation de HTTP_PROXY et HTTPS_PROXY a fait l'affaire.
pabo

2
La variante en minuscule est meilleure d'après mon expérience car elle fonctionne à la fois en wget et en curl.
Miroslav Mocek

57

Pour les variables individuelles que vous souhaitez rendre disponibles sur une base unique, vous pouvez les intégrer à la commande.

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

J'ai testé cette réponse pour un packagesous certains myPath ajouté PATHdans le .bashrcfichier (avec exportclausule). Trouve ensuite sudo PATH=$PATH which packagela bonne réponse, contrairement à sudo which package. Cependant, sudo PATH=$PATH packagene va pas plus loin que sudo package(fichier non trouvé). En revanche, lancer une plaine à packagepartir d'un shell invoqué avec sudo bashconserve le chemin étendu et donne des packagedroits sudo (deux pigeons avec une pierre). La réponse dépend donc vraiment des commandes que vous
lancez

2
La résolution PATH pour sudo est une autre affaire - si quelqu'un trouve ce message à la recherche de cette affaire, je suggère de voir unix.stackexchange.com/questions/83191/…
buckaroo1177125

24

Vous pouvez également combiner les deux env_keepdéclarations de la réponse d'Ahmed Aswani en une seule déclaration comme celle-ci:

Defaults env_keep += "http_proxy https_proxy"

Vous devriez également envisager de spécifier env_keepune seule commande comme celle-ci:

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


1

Une fonction wrapper simple (ou en ligne pour boucle)

J'ai trouvé une solution unique car:

  • sudo -E "$@" fuyait des variables qui causaient des problèmes pour ma commande
  • sudo VAR1="$VAR1" ... VAR42="$VAR42" "$@" était longue et moche dans mon cas

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

Résultat

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

Comment?

Ceci est rendu possible par une fonctionnalité de la commande bash printf. Le %qproduit une chaîne entre guillemets. Contrairement à l'expansion des paramètres dans bash 4.4 , cela fonctionne dans les versions bash <4.0


0

Si vous avez besoin de conserver les variables d'environnement dans un script, vous pouvez placer votre commande dans un document ici comme celui-ci. Surtout si vous avez beaucoup de variables pour que les choses soient bien rangées de cette façon.

# 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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.