Решение
вы должны добавить --fork
и --mount-proc
переключиться на unshare
как указано на странице руководства
-f, --fork
Fork the specified program as a child process of unshare rather than running it directly. This is useful
when creating a new PID namespace. Note that when unshare is waiting for the child process, then it
ignores SIGINT and SIGTERM and does not forward any signals to the child. It is necessary to send
signals to the child process.
Пояснение (из man pid_namespaces
)
принадлежность процесса к пространству имен PID определяется при создании процесса и не может быть изменена после этого.
то, что на самом деле делает unshare
, когда вы указываете --pid
, устанавливает дескриптор файла /proc/[PID]/ns/pid_for_children
для текущего процесса в новое пространство имен PID, в результате чего дочерние элементы, впоследствии созданные этим процессом, помещаются в другое пространство имен PID ( его дети не сами!! важно!).
Итак, когда вы передаете --fork
в unshare
, ваша программа (в данном случае busybox sh
) разветвляется как дочерний процесс unshare и помещается в новое пространство имен PID.
Зачем мне нужен --mount-proc
?
Попробуйте запустить unshare только с --pid
и --fork
и посмотрим, что произойдет.
wendel@gentoo-grill ~ λ sudo unshare --pid --fork busybox sh
/home/wendel # echo $$
1
/home/wendel # ps
PID USER TIME COMMAND
12443 root 0:00 unshare --pid --fork busybox sh
12444 root 0:00 busybox sh
24370 root 0:00 {ps} busybox sh
.
.
. // bunch more
из echo $$
мы видим, что pid на самом деле равен 1, поэтому мы знаем, что мы должны быть в новом пространстве имен PID, но когда мы запускаем ps
, мы видим другие процессы, как будто мы все еще находимся в родительском пространстве имен PID .
Это связано с тем, что /proc
— это специальная файловая система с именем procfs
, созданная ядром в памяти и взятая из справочной страницы.
Файловая система /proc
показывает (в каталогах /proc/[pid]
) только процессы, видимые в пространстве имен PID процесса, выполнившего монтирование, даже если файловая система /proc
просматривается из процессов в других пространствах имен.
Итак, чтобы такие инструменты, как ps
, работали правильно, нам нужно повторно смонтировать /proc
, используя процесс в новом пространстве имен.
Но, предполагая, что ваш процесс находится в корневом пространстве имен монтирования, если мы повторно смонтируем /proc
, это многое испортит для других процессов в том же пространстве имен монтирования, потому что теперь они ничего не видят (в /proc
). Поэтому вы также должны поместить свой процесс в новое пространство имен монтирования.
Хорошо, что у отмены общего доступа есть --mount-proc
.
--mount-proc[=mountpoint]
Just before running the program, mount the proc filesystem at mountpoint (default is /proc). This is useful when creating a new PID namespace. It also implies creating a new mount namespace since the /proc mount would
otherwise mess up existing programs on the system. The new proc filesystem is explicitly mounted as private (with MS_PRIVATE|MS_REC).
Давайте проверим, что --mount-proc
также помещает ваш процесс в новое пространство имен монтирования.
удар снаружи:
wendel@gentoo-grill ~ λ ls -go /proc/$$/ns/{user,mnt,pid}
lrwxrwxrwx 1 0 Aug 9 10:05 /proc/17011/ns/mnt -> 'mnt:[4026531840]'
lrwxrwxrwx 1 0 Aug 9 10:10 /proc/17011/ns/pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 0 Aug 9 10:10 /proc/17011/ns/user -> 'user:[4026531837]'
busybox:
wendel@gentoo-grill ~ λ doas ls -go /proc/16436/ns/{user,mnt,pid}
lrwxrwxrwx 1 0 Aug 9 10:05 /proc/16436/ns/mnt -> 'mnt:[4026533479]'
lrwxrwxrwx 1 0 Aug 9 10:04 /proc/16436/ns/pid -> 'pid:[4026533481]'
lrwxrwxrwx 1 0 Aug 9 10:17 /proc/16436/ns/user -> 'user:[4026531837]'
Обратите внимание, что их пространство имен пользователя такое же, но mount и pid разные.
Примечание. Как видите, я много цитировал со справочных страниц. Если вы хотите узнать больше о пространствах имен linux (или о чем-либо еще в Unix), первое, что вам нужно сделать, это прочитать справочную страницу каждого пространства имен. Он хорошо написан и действительно информативен.
Большое спасибо за ваш быстрый ответ! Это действительно помогает. Не могли бы вы прояснить для меня еще одну вещь. Почему я вижу из bash снаружи, что busybox все еще находится в том же пространстве имен pid, а выполнение ls -l /proc/$$/ns из busybox дает другой идентификатор пространства имен pid? Означает ли это, что я не могу видеть идентификаторы пространств имен pid контейнера с хоста?
@AndrewBolotov Извините, я не совсем понимаю ваш вопрос. Не могли бы вы перефразировать свой вопрос?
Спасибо, похоже, я указал неверный PID при проверке идентификатора пространства имен PID, и отсюда возникает путаница.