LX C - как выполнить скрипт внутри контейнера на основе определенных данных, поступающих с хоста - PullRequest
0 голосов
/ 21 февраля 2020

У меня есть Ubuntu 16:04 LX C контейнер с именем my-ubuntu , пользователь-контейнер не root с именем ag и сценарий bash с именем lxc_script. sh, расположенный на моем хост-компьютере, который является системой Ubuntu 19.10. Я пытаюсь скомпилировать и запустить программу C ++ внутри контейнера, используя lxc_script. sh. Сценарий вызывается с двумя параметрами

1.Стандартный ввод, который будет предоставлен программе C ++

2. Фактический исходный код C ++

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

./lxc_script.sh "12 22" "#include <iostream>\nusing namespace std;\nint main()\n{int a,b;cin>>a>>b; cout<<a+b; return 0;}"

PS. Два параметра не кодируются жестко в вызове сценария, вместо этого они предоставляются программой python, которая вызывает этот сценарий как подпроцесс, но это не является частью моего вопроса, поэтому мне пришлось их жестко кодировать.

Чтобы скомпилировать и запустить программу внутри контейнера, я должен выполнить следующие шаги:

  1. Введите в контейнере (то есть войдите как определенный пользователь)
  2. Сохраните исходный код (этот второй параметр) в файле. cpp (скажем, пример. cpp)
  3. Создайте исполняемый файл и запустите его, предоставив необходимый ввод (первый параметр)

Насколько я знаю, LX C предоставляет утилиту командной строки, которую можно использовать для получения оболочки в контейнере

Например, чтобы войти в оболочку bash, вы может сделать что-то вроде этого

lxc exec container_name -- /bin/bash

Проблема в том, что я хотел бы, чтобы процесс был автоматизирован c, поэтому мне не нужно вручную компилировать и запускать программу. Моя идея состоит в том, чтобы использовать lxc_script. sh для подачи ввода в оболочку bash контейнера (в основном выполняющую эти 3 шага выше)

Реализация реализации Идея выглядит примерно так:

#! /bin/bash

login_and_exec() { lxc exec my-ubuntu -- sudo --login --user ag /bin/bash<<<"$1"; }
STDIN="$2"
CONTENT="$3"


login_and_exec "
    touch example.cpp
    echo \"$CONTENT\" > example.cpp
    make example
    ./example <<< \"$STDIN\"
"

На первый взгляд, это выглядит нормально, но сразу становится проблематичным. Например,

  1. Если код C ++ содержит двойные кавычки или что-то другое специальные вещи, которые могут разбить bash строку
  2. Если я попытаюсь, скажем, поместить код во временный файл, скомпилировать его, запустить, а затем удалить временные файлы (исходный код и исполняемый файл) ), получение файлового дескриптора соответствующего временного файла (чтобы выполнить двоичный файл и удалить его после того, как я выполнил свою работу) было бы проблемой, поскольку команда, отвечающая за создание временного файла, не будет рассматриваться как часть строки, которая содержит скрипт. Как следствие, команда будет выполняться внутри lxc_script. sh, создавая временный файл внутри моей текущей папки вместо того, чтобы создавать его в контейнере!

Вот что я хотел сказать

login_and_exec "
    $tempfile=$(mktemp XXXXXXXX.cpp)
    echo \"$CONTENT\" > $tempfile
    make $tempfile
    ./$tempfile <<< \"$STDIN\"
"

Хотя я нашел исправление для проблемы № 2 (использование сопоставления для переноса команд между одинарными кавычками во избежание интерполяции), оно не работает на этот раз, потому что CONTENT больше не является строкой, когда консоль bash bash внутри контейнера запускает фрагмент

login_and_exec '
    tempfile=$(mktemp XXXXXXXX.cpp)'"
    echo \"$CONTENT\" > $tempfile
    make $tempfile
    ./$tempfile <<< \"$STDIN\"
    rm $tempfile
"

Я также попытался использовать файл вместо строки для выполняя работу в контейнере, но таким образом мне не удалось передать другому сценарию (сценарию, который выполняется в контейнере) требуемые параметры (входной и исходный код) из lxc_script. sh, который запускается на хост-компьютере, такие методы, как создание переменных среды параметров или выбор сценария для другого, становятся недоступными

#! /bin/bash

login_and_exec() { lxc exec my-ubuntu -- sudo --login --user ag /bin/bash<"$1"; }
STDIN="$2"
CONTENT="$3"


login_and_exec some_other_script.sh

Короткие задания Нация: Каков наилучший способ выполнить задачу? Извините за любые неясности или опечатки

...