다음 예를 살펴보겠습니다.
[user@user~]$ sudo docker run -d -e XYZ=123 ubuntu sleep 10000
2543e7235fa9
[user@user~]$ sudo docker exec 2543e7235fa9 echo test
test
[user@user~]$ sudo docker exec 2543e7235fa9 echo $XYZ
<empty row>
[user@user~]$ sudo docker exec -it 2543e7235fa9 bash
root@2543e7235fa9:/# echo $XYZ
123
<empty row>
대신 왜 받나요 123
? bash를 실행하고 입력한 후에 볼 수 있는 이유는 무엇입니까 XYZ=123
?
답변1
여기서 누락된 두 가지 사항은 다음과 같습니다.
docker exec ... <command>
<command>
기본적으로 셸에서 실행 되지 않고<command>
셸 없이 컨테이너에서만 실행됩니다.비대화형 셸의 docker에서 명령을 실행하려면 다음을 사용하세요.
docker exec <container> bash -c '<command>'
단어가 여러 개인 경우
<command>
전체 명령을 작은따옴표나 큰따옴표로 묶어 전달해야 합니다bash -c
.예를 들어
sudo docker exec 2543e7235fa9 bash -c 'echo $XYZ'
이 작업을 수행할 때는 두 개의 쉘을 갖는 것이 중요합니다.
- 실행 중인 셸
sudo docker exec ...
("Shell A"라고 함) - 컨테이너 내부에서 실행되는 셸("셸 B"라고 함)
만약 너라면아니요쉘 A의 백슬래시 이스케이프 또는 작은따옴표
$
및 쉘 A는 자체 값을 삽입합니다$XYZ
(값이 없더라도 빈 문자열을 반환합니다).따라서
XYZ=5
셸 A에 있는 경우 귀하의 셸sudo docker exec 2543e7235fa9 echo $XYZ
은 와 동일합니다exec 2543e7235fa9 echo 5
(docker에게 run 을 지시하지 않았기 때문에 셸 B도 없을 것입니다bash -c ...
).만약 너라면하다이스케이프 또는 작은따옴표를 사용한
$
다음 이를 있는 그대로 쉘 B에 전달하고 쉘 B는 해당 값을 삽입합니다$XYZ
.- 실행 중인 셸
즉, 다음을 사용합니다.
sudo docker exec 2543e7235fa9 bash -c 'echo $XYZ'
또는
sudo docker exec 2543e7235fa9 bash -c "echo \$XYZ"
제 생각에는 작은 따옴표 형식이 수행하는 작업과 대부분의 경우 사용해야 하는 작업을 이해하기가 더 쉽습니다. 작은따옴표 내에서는 변수 보간이 발생하지 않으므로 명령은 쉘 B에서와 동일하게 전달됩니다.
큰따옴표 형식은 셸 A에서 셸 B로 변수를 전달해야 할 때 유용합니다. 리터럴도 전달해야 하는 경우 $
백슬래시 이스케이프를 사용해야 합니다. 예를 들어, 쉘 B echo 쉘 A $ABC
및 자체가 있습니다 $XYZ
.
sudo docker exec 2543e7235fa9 bash -c "echo $ABC \$XYZ"
쉘 A $ABC
가 123이고 10
쉘 B $XYZ
가 123이면 출력은 다음과 같습니다.
10 123
$XYZ
참고: 쉘 B의 시작 파일 중 하나에 정의되지 않거나 docker run -e XYZ=123
예제에서 사용한(또는 사용 -env-file
) 경우가 아니면 값이 없습니다 .
답변2
$XYZ
명령을 실행하는 쉘에 의해 확장되기 때문입니다 docker exec
. $XYZ
문자열을 넣으 려면 인용을 해야 합니다 .
sudo docker exec ... echo \$XYZ
실제로 오해가 있습니다. 매개변수가 무엇이고 쉘에서 어떻게 작동하는지에 대한 것입니다. 당신이 달릴 때
any-command $XYZ
any-command
그런 걸 본 적이 없어요 $XYZ
. 쉘은 이를 해당 쉘에 있는 매개변수의 값으로 대체합니다. 인수를 지정하지 않았 XYZ
거나 인수가 비어 있으므로 셸에 제출하는 실제 명령줄은 다음과 같습니다.
sudo docker exec 2543e7235fa9 echo