Вопрос или проблема
Я выполняю команды в контейнере Docker, используя socat, и хочу получить код завершения кода, выполненного в контейнере.
Вот что я пробовал:
$ docker run --rm -itd --name test123 ubuntu
$ echo "ls" | socat EXEC:"docker attach test123",pty - &> /dev/null
$ echo $?
0
$ echo "foobar" | socat EXEC:"docker attach test123",pty - &> /dev/null
$ echo $?
0
Как вы можете видеть, это не работает правильно, потому что код завершения команды foobar
должен явно быть ненулевым.
$ socat -V
socat version 1.8.0.1 on
running on Darwin version
man bash
, в разделе VARIABLES
, показывает, что вам нужно:
PIPESTATUS
Переменная массива (см. Массивы), содержащая список кодов завершения
значений процессов в самом недавнем выполненном
фоновом пайплайне (который может содержать только одну команду).
Ответ или решение
Для получения кода выхода команды, выполненной в контейнере Docker с использованием socat
, необходимо правильно обрабатывать конвейеры и использовать специальную переменную в Bash, которая сохраняет статусы выхода команд в последнем выполненном конвейере.
Проблема
В вашем случае, когда вы используете socat
для отправки команды в Docker-контейнер с помощью echo
, код выхода команды не отражается должным образом. Это происходит потому, что socat
и docker attach
обрабатываются в рамках одного конвейера, и echo $?
возвращает статус выхода команды echo
, что всегда 0.
Решение
Используйте массив PIPESTATUS
, который в Bash хранит коды выхода всех команд, участвующих в последнем выполненном конвейере. Ниже приведен пример, как это можно реализовать:
# Запустите Docker контейнер
docker run --rm -itd --name test123 ubuntu
# Отправка команды в контейнер с использованием socat
echo "ls" | socat EXEC:"docker attach test123",pty - > /dev/null
# Получение кода выхода команды ls
exit_code_ls=${PIPESTATUS[0]}
echo "Exit code of ls: $exit_code_ls"
# Отправка неправильной команды
echo "foobar" | socat EXEC:"docker attach test123",pty - > /dev/null
# Получение кода выхода команды foobar
exit_code_foobar=${PIPESTATUS[0]}
echo "Exit code of foobar: $exit_code_foobar"
Объяснение кода
- docker run: Запускаем контейнер Ubuntu в фоновом режиме.
- echo "ls" | socat …: Команда
ls
отправляется в контейнер черезsocat
. - ${PIPESTATUS[0]}: Эта переменная содержит код выхода первой команды из конвейера, что в данном случае будет статус выполнения команды
ls
. - > /dev/null: Отключает вывод в терминал, потенциально улучшая читаемость.
Важные моменты
- Убедитесь, что в вашем контейнере установлены все необходимые команды.
- Если вы используете команды, которые могут завершиться с ошибкой, настройте обработку ошибок для более надежной работы.
- Следите за тем, что
docker attach
работает с активным терминалом и не может обрабатывать команды, которые не выполняют ввода/вывода через STDIN/STDOUT корректно.
Заключение
Используя переменные Bash и правильную обработку кодов выхода, вы сможете отслеживать успешность выполнения команд в Docker контейнерах с помощью socat
. Этот подход не только обеспечивает правильность обработки ошибок, но и улучшает контроль над процессами, что особенно важно в разработке и эксплуатации приложений.