Получение нескольких переменных из вывода команды docker exec в bash-скрипте?

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

Я хотел бы выполнить скрипт на хост-машине (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, чтобы извлекать переменные из контейнера и работать с ними на хосте.

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

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