Как удалить переменные окружения с помощью bash-скрипта

Вопрос или проблема

Я пытался использовать bash скрипт для добавления или удаления прокси в批量, но скрипт выполняется с запутанными результатами.

Я могу добавлять прокси批量, используя следующий код. Этот код сохранен мной в use_proxy.sh:

#!/bin/bash
PROXY="http://127.0.0.1:10889"
set_proxy() {
    export http_proxy="$PROXY"
    export https_proxy="$PROXY"
    export HTTP_PROXY="$PROXY"
    export HTTPS_PROXY="$PROXY"
    echo "Прокси установлен на $PROXY"
}
set_proxy

Когда я запускаю этот скрипт (bash use_proxy.sh) с помощью команды bash, все работает нормально, и выполнение команды env добавляет адрес прокси

Но я не могу удалить прокси批量, используя следующий код, который сохранен в unset_proxy.sh:

#!/bin/bash
unset_proxy() {
    unset http_proxy 
    unset https_proxy 
    unset HTTP_PROXY 
    unset HTTPS_PROXY
    echo "Прокси отменен"
}
unset_proxy

Когда я использую этот скрипт (т.е. запускаю bash unset_proxy.sh), этот скрипт не работает. Когда я выполняю команду env, я все еще вижу адрес прокси, ранее установленный use_proxy.sh

Почему?


Я обнаружил, что если скрипт запустить с помощью source (т.е. source unset_proxy.sh), он выполняется успешно.
Теперь у меня есть новый вопрос: почему bash unset_proxy.sh не может правильно удалить переменную окружения, в то время как source unset_proxy.sh успешно удалит переменную окружения?

Когда вы запускаете shell-скрипт, он выполняется в отдельном процессе оболочки. Это означает, что вы не можете запустить скрипт для установки или удаления переменных в текущей оболочке, и экспорт переменной не имеет значения. Возьмем тривиальный пример:

$ cat foo.sh
#!/bin/bash
export foo="bar"
echo "Foo в скрипте '$foo'"

$ $ ./foo.sh 
Foo в скрипте 'bar'

$ echo "Foo вне скрипта: '$foo'"
Foo вне скрипта: ''

Как видите, выполнение скрипта не установило переменную. Однако подключение скрипта с помощью . (или, если ваша оболочка bash, используя source, что одно и то же), который выполнит команды в текущей оболочке, позволяет вам устанавливать и удалять переменные:

$ . ./foo.sh 
Foo в скрипте 'bar'
$ echo "Foo вне скрипта: '$foo'"
Foo вне скрипта: 'bar'

Таким образом, использование . вместо запуска скриптов, вероятно, будет тем, что вам нужно. Еще проще, добавьте две функции в ваш ~/.bashrc, и затем вы сможете просто запускать их в любой оболочке и они будут работать “из коробки”. Нет необходимости в отдельных скриптах, просто скопируйте и вставьте код прямо в ваш ~/.bashrc.

Смотрите В чем разница между подключением (‘.’ или ‘source’) и выполнением файла в bash?

Ответ или решение

Для решения вашей проблемы с удалением переменных окружения в скрипте Bash важно понять различие между выполнением скрипта и его «соседним» запуском, что происходит при использовании команды source или ..

Проблема

Когда вы запускаете скрипт в терминале с помощью команды, например, bash unset_proxy.sh, этот скрипт выполняется в новом дочернем процессе. Все изменения, внесенные в переменные окружения в этом дочернем процессе, не отражаются в родительском процессе (вашем текущем терминале). Это будет очевидно, поскольку после завершения скрипта переменные остаются в исходном состоянии.

Решение

Чтобы удалить переменные окружения так, как вы и намеревались, необходимо использовать команду source (или сокращенно .) вместо обычного запуска скрипта. Например:

source unset_proxy.sh

Или:

. unset_proxy.sh

Таким образом, команды внутри unset_proxy.sh будут выполняться в вашем текущем контексте оболочки, и переменные окружения будут действительно удалены.

Примеры

  1. Создание и выполнение скрипта (дочерний процесс):

    # foo.sh
    #!/bin/bash
    export foo="bar"
    echo "Foo в скрипте: '$foo'"

    Выполнение:

    bash foo.sh
    echo "Foo вне скрипта: '$foo'"  # Вывод: Foo вне скрипта: ''
  2. Использование source (текущий процесс):

    # foo.sh
    #!/bin/bash
    export foo="bar"
    echo "Foo в скрипте: '$foo'"

    Выполнение:

    source foo.sh
    echo "Foo вне скрипта: '$foo'"  # Вывод: Foo вне скрипта: 'bar'

Рекомендации

Если вы часто работаете со скриптами для установки и удаления переменных окружения, вы можете рассмотреть возможность добавления этих функций прямо в ваш ~/.bashrc файл. Это упростит настройку среды в вашем терминале для любой сессии. Например:

# Добавьте в ~/.bashrc
set_proxy() {
    export http_proxy="http://127.0.0.1:10889"
    export https_proxy="http://127.0.0.1:10889"
}

unset_proxy() {
    unset http_proxy
    unset https_proxy
}

После этого вы можете выполнять set_proxy и unset_proxy напрямую в вашем терминале, не создавая отдельные скрипты.

Заключение

Использование source или . для запуска вашего скрипта — это лучший метод изменения переменных окружения в текущей сессии. Убедитесь, что вы понимаете отличие между выполнением в дочернем процессе и выполнением в текущем процессе, чтобы избежать подобных недоразумений в будущем.

Оцените материал
Добавить комментарий

Капча загружается...