Разыменование переменной среды при расширении параметра в сценарии оболочки
Я пытаюсь разыменовать значение переменной среды, используя расширение параметра $@
, но похоже, что это не работает.
Мне нужно вызвать сценарий оболочки с определенными аргументами. Список аргументов содержит переменные среды, и ожидается, что переменные среды будут присутствовать там, где должен выполняться сценарий оболочки. Я не знаю заранее список команд, поэтому я расширяю этот список команд, используя$@
. Однако сценарий не может отменить ссылку на значение переменных среды.
Минимальная настройка, объясняющая мою проблему, может быть выполнена, как показано ниже.
- Dockerfile
FROM alpine:3.10
ENV MY_VAR=production
WORKDIR /app
COPY run.sh .
ENTRYPOINT [ "sh", "run.sh" ]
- run.sh
#!/bin/sh
echo "Value of MY_VAR is" $MY_VAR
echo "Begin"
$@
echo "Done"
Я могу создать образ, используя docker build . -t env-test
. Когда я запускаю его, используяdocker run env-test:latest 'echo $MY_VAR'
, Я получаю следующий результат.
Value of MY_VAR is production
Begin
$MY_VAR
Done
В то время как ожидаемый результат:
Value of MY_VAR is production
Begin
production
Done
SideNote: На самом деле я пытаюсь запустить его, используя файл набора, как показано ниже:
version: '3'
services:
run:
image: env-test:latest
command: echo $$MY_VAR
но он снова дает мне аналогичный результат.
3 ответа
Расширяя eval
Вот простой сценарий bash, который будет использовать eval для оценки строки как последовательности команд bash:
#!/usr/bin/env bash
echo program args: $@
eval $@
но будьте осторожны, eval
сопряжено с опасностями:
https://medium.com/dot-debug/the-perils-of-bash-eval-cc5f9e309cae
Первым делом, $@
он просто напечатает номер аргумента
#!/bin/sh
echo "Value of MY_VAR is" $MY_VAR
echo "Begin"
$@
echo "Done"
$@ = сохраняет все аргументы в виде списка строк
$* = сохраняет все аргументы как одну строку
$# = сохраняет количество аргументов
Что означает $ @ в сценарии оболочки?
Во-вторых, при запуске следующей команды
docker run env-test:latest 'echo $MY_VAR'
Он будет искать $MY_VAR в хост-системе, а не в контейнере.
Чтобы получить доступ к контейнеру env, вы должны передать их как -e MY_VAR=test
, а не в качестве аргумента для команды запуска докера, которая будет в ENV в host.
docker run -e MY_VAR=test env-test:latest
Итак, ценность MY_VAR
будет test
не production
.
Чтобы отладить аргумент docker run
export MY_VAR2="value_from_host"
Теперь беги
docker run env-test:latest "echo $MY_VAR2"
поэтому значение будет value_from_host
потому что аргумент выбирается у хоста.
Есть еще несколько способов снять шкуру с этой кошки:
me@computer:~$ docker run -it --rm ubuntu:20.04 bash -c 'echo $HOSTNAME'
e610946f50c1
Здесь мы вызываем bash внутри контейнера для обработки всего, что находится внутри одинарных кавычек, поэтому подстановка и / или расширение переменных применяется не вашей оболочкой, а оболочкой внутри контейнера.
Другой подход:
me@computer:~$ cat test.sh
#!/bin/bash
echo $HOSTNAME
me@computer:~$ cat test.sh | docker run -i --rm ubuntu:20.04 bash
62ba950a60fe
В этом случае,
Примечание. Имя хоста в каждом примере разное, потому что я использую