Я изучаю контейнерные технологии Linux и написал минимальную реализацию контейнера самостоятельно. В настоящее время я запутался в консолях / терминалах для процессов контейнера, поскольку я «повторно использую» управляющий терминал как /dev/console
(вместо c 5 1
) в контейнере.
Я определяю текущий терминал из /proc/self/fd/0
и /proc/self/fd/2
, считываю его узел устройства (основной и второстепенный) и mknod(2)
использую обнаруженные узлы устройства для создания /dev/console
узла в контейнере.
Это нормально при запуске обычного приложения, например, /bin/sh
PID 1 (в пространстве имен PID), но не при использовании системы инициализации (я использовал для этого BusyBox).
Вот мой вариант /etc/inittab
для BusyBox rootfs:
::sysinit:/bin/true
::respawn:-/bin/sh
Однако оболочка, порожденная init, всегда жалуется can't access tty; job control turned off
. Я также пробовал использовать тот же узел TTY хоста для /dev/tty
(вместо c 5 0
), но эта проблема все еще сохраняется.
Я посмотрел исходный код systemd-nspawn
и обнаружил, что онсоздает «пересланный pty», где контейнер работает на новом PTY, который "пересылается" на хостовую сторону. Код слишком сложен для моего образовательного проекта, поэтому он нежизнеспособен для меня.
Как использовать хост-терминал для контейнера?
Подробности: В моей программе-контейнере clone(2)
есть только один дочерний элемент с флагами = CLONE_NEWGROUP | CLONE_NEWNET | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD
, и дочерний элемент устанавливает возможности (черный список) и seccomp (белый список, список системных вызовов взят изДокер), прежде чем pivot_root(2)
в контейнер rootfs и execve(2)
в целевое приложение.
В настоящее время я экспериментирую с Linux 5.3 (Ubuntu 18.04 HWE), но не ожидаю, что ситуация будет отличаться от ситуации в более поздних версиях Linux.