Вопрос или проблема
Я хотел бы выполнить скрипт на хост-машине (script_on_host.sh
), который затем обращается внутрь контейнера Docker, чтобы получить некоторые данные с помощью второго скрипта (script_in_container.sh
). Данные доступны только внутри контейнера и недоступны напрямую с хоста, поэтому я делаю это таким образом.
У меня возникают проблемы с передачей данных между двумя скриптами. Я попробовал следующее:
script_in_container.sh
#!/bin/bash
x=1
y=2
z=6.3
echo $x
echo $y
echo $z
script_on_host.sh
#!/bin/bash
results=$(docker exec mycontainer './script_in_container.sh')
X=$results(1)
Y=$results(2)
Z=$results(3)
Но это вызывает ошибку. Может кто-то помочь мне с этим? Есть ли хороший или более стандартный способ передачи переменных таким образом? Мне кажется, я делаю что-то немного неуклюже, используя echo для вывода нескольких строк из скрипта контейнера.
Самое простое решение будет использовать set --
для присвоения переменных
из контейнера Docker позиционным параметрам вот так:
#!/bin/bash
results=$(docker exec mycontainer './script_in_container.sh')
saveIFS=$IFS
IFS=$'\n'
set -- $results
IFS=$saveIFS
echo результат 1: "$1"
echo результат 2: "$2"
echo результат 3: "$3"
Вы можете использовать readarray для создания массива результатов, разделенных новой строкой.
readarray -t results < <(docker exec mycontainer './script_in_container.sh')
x=${results[0]}
y=${results[1]}
z=${results[2]}
Вы можете использовать sed, вот так:
#!/bin/bash
results=$(docker exec mycontainer './script_in_container.sh')
X=$(echo "$results" |sed '1q;d')
Y=$(echo "$results" |sed '2q;d')
Z=$(echo "$results" |sed '3q;d')
Выражение sed на самом деле содержит две команды:
1q
— это команда для нахождения первой строки и выхода;
— это разделитель командd
удаляет текущую строку.
В случае чтения первой строки d
является как бы избыточным, поскольку sed завершит выполнение после вывода первой строки, но для других строк d
необходима для удаления строк, которые не соответствуют вашей первой команде.
Ответ или решение
Чтобы получить несколько переменных из вывода команды docker exec
в bash-скрипте, существует несколько подходов. Ваш сценарий состоит в том, чтобы выполнить скрипт внутри контейнера и извлечь значения, которые затем будут использоваться в скрипте на хосте. Рассмотрим несколько методов для достижения этой цели.
Метод 1: Использование set --
Этот метод позволяет вам присваивать переменные с помощью позиционных параметров. Пример скрипта script_on_host.sh
может выглядеть следующим образом:
#!/bin/bash
results=$(docker exec mycontainer './script_in_container.sh')
saveIFS=$IFS
IFS=$'\n'
set -- $results
IFS=$saveIFS
echo "Результат 1: $1"
echo "Результат 2: $2"
echo "Результат 3: $3"
Объяснение:
- Мы сохраняем текущее значение IFS (Internal Field Separator), устанавливаем его так, чтобы строки разбивались по символу новой строки.
- Затем используем команду
set --
, чтобы разбить вывод на позиционные параметры. - Наконец, мы выводим значения переменных.
Метод 2: Использование readarray
Этот подход позволяет удобно сохранять результаты в массиве, что делает код более читаемым и управляемым:
#!/bin/bash
readarray -t results < <(docker exec mycontainer './script_in_container.sh')
x=${results[0]}
y=${results[1]}
z=${results[2]}
echo "x: $x"
echo "y: $y"
echo "z: $z"
Объяснение:
readarray
читает вывод команды по строкам и сохраняет их в массивеresults
.- Мы можем легко получить доступ к переменным с помощью индексов массива.
Метод 3: Использование sed
Это решение позволяет извлекать конкретные строки с помощью команды sed
, что может быть полезно для обработки вывода:
#!/bin/bash
results=$(docker exec mycontainer './script_in_container.sh')
X=$(echo "$results" | sed '1q;d')
Y=$(echo "$results" | sed '2q;d')
Z=$(echo "$results" | sed '3q;d')
echo "X: $X"
echo "Y: $Y"
echo "Z: $Z"
Объяснение:
- Используем
sed
для вывода конкретной строки. - Команда ‘1q;d’ выводит первую строку и завершает выполнение, что эффективно для извлечения нужных данных.
Заключение
Каждый из предложенных методов имеет свои преимущества. Выбор подхода зависит от ваших предпочтений и контекста. Использование массива (readarray
) предлагает простоту и производительность, в то время как позиции параметров и sed
обеспечивают больше контроля над извлекаемыми данными.
Используйте один из предложенных методов в своем скрипте script_on_host.sh
, чтобы извлекать переменные из контейнера и работать с ними на хосте.