Назад | Перейти на главную страницу

Почему переменные среды отличаются от `bash -c`

Как получилось следующее, т.е. повторение $PATH прямо из bash -c:

docker exec -i -t my_container bash -c "echo $PATH"

возвращает другое значение для $PATH чем то, что следует, т.е. запуск интерактивного сеанса bash и повторение $PATH?

docker exec -i -t my_container bash 
root@21e6d898c3c2:/# echo $PATH

Чтобы дать некоторый контекст для этого вопроса, я хотел бы запустить команду в контейнере с docker exec, и эта команда находится на пути, если я запускаю интерактивный сеанс bash, но нет, если я просто запускаю команду.

В этом случае использование полного пути к исполняемому файлу не является обходным решением, поскольку команда полагается на другие переменные среды, которые, как и PATH установлены в интерактивном сеансе bash, но не в том случае, если я запустил команду прямо.

В вашем первом примере:

docker exec -i -t my_container bash -c "echo $PATH"

Это позволит оценить $PATH переменную с вашей оболочкой на вашем докере-клиенте, вне контейнера, а затем передайте развернутое значение в качестве команды для запуска внутри контейнера. Вы можете сравнить значение вышеперечисленного с бегом echo $PATH в командной строке вне докера и убедитесь, что они совпадают.

Во втором примере:

docker exec -i -t my_container bash 
root@21e6d898c3c2:/# echo $PATH

Это позволит оценить $PATH переменная внутри контейнера.

Вы можете избежать первого примера или заключить его в одинарную кавычку, чтобы оболочка bash на вашей рабочей станции не расширила его, чтобы он оценивался внутри контейнера. Любой из следующих вариантов будет работать:

docker exec -i -t my_container bash -c "echo \$PATH"
docker exec -i -t my_container bash -c 'echo $PATH'

когда -c указан bash не работает как интерактивный или авторизоваться shell, чтобы он не читал одни и те же сценарии запуска. Все, что установлено в /etc/profile, ~/.bash_profile, ~/.bash_login, или ~/.profile определенно будет пропущен.

Кроме того, как объясняет bash страница руководства:

Bash пытается определить, когда он запускается со своим стандартным вводом, подключенным к сетевому соединению, как при выполнении удаленным демоном оболочки, обычно rshd, или демон безопасной оболочки sshd. Если bash определяет, что он запускается таким образом, он читает и выполняет команды из ~/.bashrc и ~/.bashrc, если эти файлы существуют и доступны для чтения.

Так что, если он не думает, что вы подключаетесь по сети, он может не прочитать .bashrc файл, который пропустил бы все, что не было пропущено на предыдущем шаге.

решение

Чтобы обойти эту проблему, я бы создал сценарий, который устанавливает PATH на что-нибудь подходящее, а затем запустите команду. Если вы хотите использовать существующий .profile или другие файлы, тогда вы можете просто источник в вашем сценарии.

Попробуйте -l вариант для bash. Он запустится в оболочке входа и загрузит /etc/profile.

docker exec -i -t my_container bash -lc "echo $PATH"