아시다시피 OCI 컨테이너(일반적으로 Docker 컨테이너라고 함)는 진입점 프로세스(컨테이너 네임스페이스 내에서 PID1이라고도 함)가 종료되면 종료됩니다.
하지만 이 컨테이너 내에서 셸 액세스 권한과 루트 권한이 있는 경우 이 PID 1 프로세스를 핫 교체할 수 있는 방법이 있는지 궁금합니다.
PID1이 프로세스라고 가정해 보겠습니다 . 컨테이너를 종료하지 않고 PID를 유지하면서(프로세스 자체에서 실행된 것처럼) [/bin/sleep, 99999]
완전히 새로운 프로세스로 교체할 수 있는 방법이 있습니까 ?[/bin/sleep, 100]
이 질문은 실행 파일을 바꾸는 것이 아니라 실행 중인 프로세스 자체를 다른 프로세스로 바꾸는 것에 관한 것입니다.
답변1
마치 프로세스 자체에서 실행된 것처럼
방법은 프로세스가 execve를 호출하도록 하는 것입니다.
이것이 디버거가 하는 일입니다.
최소한 프로세스를 실행하는 사용자의 권한이 필요합니다. 설정에 따라 다름kernel.yama.ptrace_scope
, 컨테이너 내부에서 루트가 되어야 할 수도 있습니다. 이는 일반적으로 동일합니다. 컨테이너 외부에 어떤 권한이 적용되는지 잘 모르겠습니다. 어떻게 해야 하는지 모르겠습니다.ptrace 액세스 확인 규칙Docker와 상호작용합니다.
sh와 gdb를 사용하는 스크립트입니다. 컨테이너 내부(PID로 1 전달) 또는 외부(컨테이너 초기화 프로세스의 PID 전달)에서 실행할 수 있습니다.
#!/bin/sh
set -e
help_and_exit () {
cat <<EOF
Usage: $0 PID COMMAND [ARG...]
Use gdb to replace the running process PID by the specified command.
EOF
exit $1
}
if [ "$1" = "--help" ]; then
help_and_exit
elif [ $# -lt 2 ]; then
help_and_exit 120 >&2
fi
pid=$1; shift
# Quote the command path and the arguments as a C string.
args=
add_arg () {
args="$args\""
while case "$1" in *[\\\"]*) true;; *) false;; esac; do
set -- "${1#*[\\\"]}" "${1%"${1#*[\\\"]}"}"
args="$args${2%?}\\${2#"${2%?}"}"
done
args="$args$1\", "
}
add_arg "$1"
args="$args$args"; shift
for x; do
add_arg "$x"
done
args="${args}(char*)0"
gdb -n -pid "$pid" -batch -ex "call execlp($args)"
gdb를 설치하고 싶지 않다면 Python이나 C(또는 원하는 언어)로 필요한 설치를 수행하는 작은 프로그램을 작성할 수 있습니다.ptrace
수신 전화.
컨테이너의 PID 1이 init로 사용하기 위한 프로그램인 경우 자체적으로 다시 실행하도록 지시하는 방법이 있을 수 있으므로 이를 사용해야 합니다. 프로그램은 실행 전에 삭제될 수 있으며, 후속 실행 파일에는 파일이나 환경 변수 등의 추가 데이터가 전달될 수 있습니다.