Экземпляры Bash не вложены в Dockerfile `RUN` - PullRequest
4 голосов
/ 26 октября 2019

Вложенный экземпляр bash увеличивает переменную среды SHLVL (http://tldp.org/LDP/abs/html/internalvariables.html).

Например:

$ echo $SHLVL
1
$ bash -c "echo \$SHLVL"
2
$ bash -c "bash -c 'echo \$SHLVL'"
3

См., Что в https://github.com/dgroomes/docker-shell-example/commit/60091eb63545f24a9fb3ccf38649ea5098bdbd0d/checks?check_suite_id=283012138#step:5:2

Нокогда я пытаюсь сделать то же самое в Dockerfile, SHLVL остается в 1. Почему?

См. минимальный воспроизводимый пример в https://github.com/dgroomes/docker-shell-example/blob/60091eb63545f24a9fb3ccf38649ea5098bdbd0d/Dockerfile#L5. И для большего доказательства, выполнение этого Dockerfile винструмент CI Github Actions в https://github.com/dgroomes/docker-shell-example/commit/60091eb63545f24a9fb3ccf38649ea5098bdbd0d/checks?check_suite_id=283012138#step:8:15

Вот проблема, которая сводится к четырем строкам (следует вывести 2, а затем 0):

Step 2/2 : RUN bash -c "bash -c 'echo \$SHLVL; echo \$BASH_SUBSHELL'"
 ---> Running in ce2362419426
1
0

Ответы [ 2 ]

2 голосов
/ 28 октября 2019

Этот ответ, возможно, все еще неполон, но очарован проблемой, я потратил некоторое время на его отладку, используя следующий Dockerfile:

FROM debian:10
SHELL ["/bin/sh", "-ec"]
RUN apt-get update > /dev/null; apt-get -y install psmisc > /dev/null

# First layer is good: expected 1, got 1
RUN /bin/bash -exc "pstree; echo SHLVL=\$SHLVL"

# The surprising example (getting the escaping right is already tricky)
RUN /bin/bash -exc "/bin/bash -exc \"pstree; echo SHLVL=\\\$SHLVL\"" # expected 2, got 1
RUN /bin/bash -exc "/bin/bash -exc \"/bin/bash -exc \\\"pstree; echo SHLVL=\\\\\\\$SHLVL\\\"\"" # expected 3, got 1

# Now what happens if two commands run in the inner bash
RUN /bin/bash -exc ":; /bin/bash -exc \":; pstree; echo SHLVL=\\\$SHLVL\"" # expected 2, got 1
RUN /bin/bash -exc ":; /bin/bash -exc \":; /bin/bash -exc \\\":; pstree; echo SHLVL=\\\\\\\$SHLVL\\\"\"" # expected 3, got 1

Интересная вещь, кажется: В случае bash за вызовом следует непосредственно другой, он будет «оптимизирован» (?). Насколько я могу судить, это не специфичная для Docker вещь, потому что она может быть воспроизведена в интерактивном режиме (в моей системе Debian 10 интерактивная последовательность команд из вопроса производит 1, 2, 2, а не 1, 2, 3 длявложенность!).

В любом случае вывод сборки Dockerfile выглядит следующим образом:

Sending build context to Docker daemon  30.21kB
Step 1/8 : FROM debian:10
 ---> 8e9f8546050d
Step 2/8 : SHELL ["/bin/sh", "-ec"]
 ---> Running in 3509ef249c45
Removing intermediate container 3509ef249c45
 ---> 8956c1fddb7c
Step 3/8 : RUN apt-get update > /dev/null; apt-get -y install psmisc > /dev/null
 ---> Running in 5cabec19144a
debconf: delaying package configuration, since apt-utils is not installed
Removing intermediate container 5cabec19144a
 ---> 64cad97f7793
Step 4/8 : RUN /bin/bash -exc "pstree; echo SHLVL=\$SHLVL"
 ---> Running in 22a0aa663163
+ pstree
sh---bash---pstree
+ echo SHLVL=1
SHLVL=1
Removing intermediate container 22a0aa663163
 ---> 4caa146b24f6
Step 5/8 : RUN /bin/bash -exc "/bin/bash -exc \"pstree; echo SHLVL=\\\$SHLVL\"" # expected 2, got 1
 ---> Running in 538ff45db230
+ /bin/bash -exc 'pstree; echo SHLVL=$SHLVL'
+ pstree
sh---bash---pstree
SHLVL=1
+ echo SHLVL=1
Removing intermediate container 538ff45db230
 ---> 1d4c9c2638fa
Step 6/8 : RUN /bin/bash -exc "/bin/bash -exc \"/bin/bash -exc \\\"pstree; echo SHLVL=\\\\\\\$SHLVL\\\"\"" # expected 3, got 1
 ---> Running in 3f0650d4d21b
+ /bin/bash -exc '/bin/bash -exc "pstree; echo SHLVL=\$SHLVL"'
+ /bin/bash -exc 'pstree; echo SHLVL=$SHLVL'
+ pstree
sh---bash---pstree
SHLVL=1
+ echo SHLVL=1
Removing intermediate container 3f0650d4d21b
 ---> 2d977033884d
Step 7/8 : RUN /bin/bash -exc ":; /bin/bash -exc \":; pstree; echo SHLVL=\\\$SHLVL\"" # expected 2, got 1
 ---> Running in 39b79af0f558
+ :
+ /bin/bash -exc ':; pstree; echo SHLVL=$SHLVL'
+ :
+ pstree
sh---bash---bash---pstree
+ echo SHLVL=2
SHLVL=2
Removing intermediate container 39b79af0f558
 ---> 48170e9bcb01
Step 8/8 : RUN /bin/bash -exc ":; /bin/bash -exc \":; /bin/bash -exc \\\":; pstree; echo SHLVL=\\\\\\\$SHLVL\\\"\"" # expected 3, got 1
 ---> Running in 456e6ec421ca
+ :
+ /bin/bash -exc ':; /bin/bash -exc ":; pstree; echo SHLVL=\$SHLVL"'
+ :
+ /bin/bash -exc ':; pstree; echo SHLVL=$SHLVL'
+ :
+ pstree
sh---bash---bash---bash---pstree
+ echo SHLVL=3
SHLVL=3
Removing intermediate container 456e6ec421ca
 ---> 30a07d3bdc95
Successfully built 30a07d3bdc95
Successfully tagged test:latest

Наконец, вывод pstree интересен, потому что он показывает, как на самом деленикакой другой процесс bash не выполняется в соответствующих точках (т. е. переменная правильно отслеживает фактическое вложение оболочки во всех случаях, просто иногда бывает меньше работающих оболочек, чем ожидалось).

0 голосов
/ 29 октября 2019

Только что выглядел правильно, я сначала наблюдаю следующее, захожу в Dockerfile и набираю что-то вроде 'RUN gfddlgjkdlfgjk', он выдаст ошибку и скажет

'/bin/sh -c gfddlgjkdlfgjk' returned a non-zero code

Из этого мы выводим, что

RUN bash -c "bash -c 'echo \$SHLVL'"

На самом деле выполняет

/bin/sh -c "bash -c \"bash -c 'echo \$SHLVL'\""

Это действительно 1 вне Docker

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...