繁体   English   中英

Bash 实例未嵌套在 Dockerfile `RUN` 中

[英]Bash instances are not nesting in Dockerfile `RUN`

嵌套的 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 中尝试相同的操作时,SHVLL 保持在 1。为什么?

请参阅https://github.com/dgroomes/docker-shell-example/blob/60091eb63545f24a9fb3ccf38649ea5098bdbd0d/Dockerfile#L5中的最小可重现示例。 And for more proof, the execution of this Dockerfile in the CI tool Github Actions at https://github.com/dgroomes/docker-shell-example/commit/60091eb63545f24a9fb3ccf38649ea5098bdbd0d/checks?check_suite_id=283012138#step:8:15

这是一个浓缩为 4 行的问题(它应该打印 2 和 0):

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

这个答案可能仍然不完整,但对这个问题很着迷,我花了一些时间使用以下 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 的 output 如下:

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 output 很有趣,因为它显示实际上没有其他 bash 进程在各个点运行(即变量跟踪实际的 Z2591C98B70119FE624898B1E424B5E91预期的)。

您的日志中有提示:

Running in 7872acbf75d7
Running in e252f3964dda

每个命令都在不同的容器中运行。

现在刚刚仔细看了一下,我首先观察到以下内容,Dockerfile 中的 go,然后输入类似“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'\""

这确实是 Docker 之外的 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM