Як зберегти змінні середовища при використанні sudo


425

Коли я використовую будь-яку команду з sudo, змінних середовища немає. Наприклад, після встановлення HTTP_PROXY команда wgetпрацює нормально без sudo. Однак якщо я набираю sudo wgetйого, він не може обійти налаштування проксі.



Відповіді:


475

Спочатку потрібно export HTTP_PROXY. По-друге, вам потрібно man sudoуважно прочитати і звернути увагу на -Eпрапор. Це працює:

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

Ось цитата зі сторінки 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
велика єдина проблема, яка полягає в зміні деяких конфігураційних файлів, наприклад, pacman для арки, щоб зробити -E передано
Ахмед Асвані

7
Щоб дозволити -E (зберегти середовище) для wget, вам потрібно вказати тег SETENV у правилі sudo, що дозволяє запускати wget - Приклад: <користувацьке ім'я> ALL = (root) NOPASSWD: SETENV: <шлях до wget>
Джон Боуерс

65
Цей "-E" не працює, якщо змінна PATH або PYTHONPATH.
apporc

Також не працює з жодною LC_*змінною. Тому просто робіть export LOL_FOO=$LC_FOOі використовуйте LOL_FOOзамість цього.
luckydonald

9
Це не працює з більш простим випадком додавання одного елемента до PATHв .bashrcфайлі - скажімо, export PATH=myPath:$PATH. Якщо я набираю sudo -E bash -c 'echo $PATH', то PATHне містить myPath, ймовірно, тому sudoщо вже вимкнув місцеве значення PATHперед викликом bash. Швидше за все, я знайшов відповідь нижче stackoverflow.com/a/33183620/5459638 ефективним, тобтоsudo PATH=$PATH command
XavierStuvw

310

Хитрість полягає в тому, щоб додати змінні середовища до sudoersфайлу за допомогою sudo visudoкоманди та додати ці рядки:

Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"

взято з Вікі ArchLinux .

Для Ubuntu 14 потрібно вказати в окремих рядках, оскільки він повертає помилки для багато змінних рядків:

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

11
Це, мабуть, найкращий варіант, щоб уникнути витоку інформації та безпеки дірок. sudo -Eце впевнений спосіб adhoc отримати той самий ефект для
разового

Я зіткнувся з проблемою того, що процес є тим, хто викликає sudo (jhbuild), і я не можу сказати йому передати прапор -E на sudo, тому це моє рішення.
jgomo3

60
Зверніть увагу, що ви ніколи не повинні редагувати etc/sudoersбезпосередньо. Натомість використовуйте visudoкоманду, яка синтаксисом перевіряє ваші зміни, перш ніж перезаписати sudoersфайл. Таким чином, ви не заблокуєте себе, якщо помилитесь під час редагування.
Хеннінг

1
Подумайте про те, як використовувати великі регіони env vars. У моєму випадку використання HTTP_PROXY та HTTPS_PROXY зробили свою справу.
пабо

2
З мого досвіду кращий варіант малі, оскільки він працює як у wget, так і в curl.
Мирослав Моцек

57

Для окремих змінних, які ви хочете зробити доступними одноразово, ви можете зробити їх частиною команди.

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

Я перевірив цю відповідь на параметр packagemyPath, доданий PATHу .bashrcфайл (із exportклаузулою). Тоді sudo PATH=$PATH which packageзнаходить правильну відповідь, на відміну від sudo which package. Однак sudo PATH=$PATH packageне йде далі sudo package(файл не знайдено). З іншого боку, запуск рівнини packageз оболонки, на яку посилається, sudo bashзберігає розширений шлях і дає packageправа судо (два голуби з одним каменем). Тож відповідь дійсно залежить від того, які команди ви запускаєте
XavierStuvw

2
Рішення PATH для судо - інша справа - чи повинен хтось знайти цю публікацію у пошуках цього питання, я пропоную переглянути unix.stackexchange.com/questions/83191/…
buckaroo1177125

24

Ви також можете поєднати два env_keepтвердження у відповіді Ахмеда Асвані в одне таке твердження:

Defaults env_keep += "http_proxy https_proxy"

Слід також розглянути можливість вказівки env_keepлише на одну команду на зразок цієї:

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


1

Проста функція обгортки (або лінія для циклу)

Я придумав унікальне рішення, оскільки:

  • sudo -E "$@" протікав змінні, що спричиняло проблеми для моєї команди
  • sudo VAR1="$VAR1" ... VAR42="$VAR42" "$@" в моєму випадку було довго і потворно

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

Результат

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

Як?

Це стає можливим завдяки функції bash вбудованого printf. %qВиробляє оболонки лапок. На відміну від розширення параметрів у bash 4.4 , це працює у bash версіях <4.0


0

Якщо у вас є необхідність зберігати змінні середовища в сценарії, ви можете помістити свою команду в ось такий документ, як цей. Особливо, якщо у вас є безліч змінних для того, щоб речі виглядали впорядковано таким чином.

# 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.