다음 내용의 스크립트가 있습니다.
sudo machinectl start "$machinename"
sudo systemd-run -PM root@"$machinename" "$command"
Failed to connect to bus: No such file or directory
Failed to start transient service unit: Transport endpoint is not connected
첫 번째 줄은 컨테이너를 시작하기 때문에 실패합니다. 두 번째 줄은 컨테이너 시작이 완료되기 전에 실행됩니다. 현재 컨테이너의 상태를 계속 폴링하고 준비가 될 때까지 차단하는 솔루션이 있습니다.
while [ "$(sudo systemctl show "systemd-nspawn@$machinename" -P StatusText)" != "Container running: Ready." ]
do
true
done
컨테이너 상태를 지속적으로 폴링하지 않고 컨테이너 시작이 완료될 때까지 어떻게 기다릴 수 있나요?
답변1
당신이하고 싶은 일에 따라 다릅니다. 귀하의 질문에 직접 답변한 다음 몇 가지 대안을 드리겠습니다. 컨테이너에서 init 시스템으로 systemd를 사용하고 있다고 가정합니다. 컨테이너 OS가 Debian/Arch/Ubuntu 또는 이와 유사한 기반인 경우 실제로 그렇습니다.
nspawn 컨테이너를 시작한 후 명령을 실행합니다.
.nspawn
파일( /etc/systemd/nspawn/yourcontainer.nspawn
) 에 다음을 추가합니다.
[Exec]
NotifyReady=yes
그런 다음 sudo machinectl start yourcontainer
컨테이너가 종료되기 전에 시작이 완료될 때까지 기다립니다. 이제 컨테이너가 준비되었으므로 스크립트의 두 번째 줄이 작동합니다(컨테이너가 시작되지 않아 폴링이 무한 루프에 빠지지 않는 한).
내부적으로 호스트는 systemd-nspawn
컨테이너에 Unix 도메인 소켓을 설정하고 있습니다. /run/host/notify
컨테이너의 systemd가 준비되면(즉, multi-user.target
대상에 도달하면) READY=1
해당 소켓에 알림을 보냅니다. 호스트의 systemd-nspawn
서비스가 메시지 수신을 기다리고 있습니다.
이 접근 방식의 단점은 더 이상 컨테이너를 비동기식으로 시작할 수 없다는 것입니다( &
기호를 사용하지 않는 한). 이는 디버깅 중이고 시작 시간이 긴 경우 성가실 수 있습니다.
기타 방법(복잡도 순):
chroot에서 명령 실행
컨테이너가 실행되고 있지 않다고 가정하면,
sudo chroot /var/lib/machines/yourcontainer /bin/bash -c "$command"
이는 방금 컨테이너를 생성하고 프로그래밍 방식으로 여러 번 초기화한 경우에 유용합니다. 분명히 샌드박스 기능의 이점을 얻지 못하는 것 같습니다. PrivateUsers=yes
파일이 chown
높은 UID로 편집되므로 이전에 동일한 컨테이너를 실행한 경우에도 작동하지 않습니다 . 컨테이너가 이미 실행 중인 경우 정의되지 않은 결과가 나타날 수 있습니다.
systemd-nspawn을 직접 사용
이 방법은 과연아니요NotifyReady=yes|no
위의 설명이 필요합니다 .
systemd-nspawn -M yourcontainer -P /bin/bash -c "$command"
이렇게 하면 모든 샌드박스가 활성화된 컨테이너 내에서 명령이 실행되지만 명령은 유일한 프로세스로(및 PID=1
) 실행됩니다. 즉, init 서비스가 실행되지 않습니다. 예를 들어, 호스트 네트워킹을 사용하지 않는 한 네트워킹을 사용할 수 없습니다.
컨테이너가 이미 실행 중이면 이 명령은 아무런 효과가 없습니다.
소켓 활성화
컨테이너의 서버가 준비될 때까지 기다리는 경우 소켓 활성화를 사용하면 됩니다(서버가 호환된다고 가정). 이것은다른 곳에서 더 나은 설명요약하면 systemd는 소켓(예: TCP 포트 80)에 대한 연결을 기다립니다. 클라이언트가 연결되면 systemd는 컨테이너를 시작한 다음 컨테이너로 트래픽을 전달합니다. 고대에도 inetd
똑같은 일이 행해졌습니다 .
이를 위해서는 파일 [email protected]
에 있는 것과 같은 줄이 필요합니다 .socket
.