Bash实例未嵌套在Dockerfile`RUN`中 [英] Bash instances are not nesting in Dockerfile `RUN`

查看:75
本文介绍了Bash实例未嵌套在Dockerfile`RUN`中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嵌套的bash实例会递增SHLVL环境变量( http://tldp.org /LDP/abs/html/internalvariables.html )。

A nested bash instance increments the SHLVL environment variable (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 。为了获得更多证明,请在CI工具Github Actions中的 https://github.com/dgroomes/docker-shell-example/commit/60091eb63545f24a9fb3ccf38649ea5098bdbd0d/checks?check_suite_id=283012138#step:8:15

See the Minimal, Reproducible Example at 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):

Here is the problem distilled down to 4 lines (it should print 2 and then 0):

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


推荐答案

这个答案可能仍然不完整,但是对这个问题着迷,我花了一些时间使用以下Dockerfile对其进行调试:

This answer is possibly still incomplete, but fascinated by the problem, I have taken some time to debug it using the following 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)

The interesting thing seems to be: In case a bash invocation is followed directly by another one, it will be "optimized" (?) away. As far as I can tell, this is not a Docker-specific thing, because it can be reproduced interactively (on my Debian 10 system, the interactive command sequence from the question produces 1, 2, 2 and not 1, 2, 3 for the nesting!).

无论如何,构建Dockerfile的输出如下:

In any case, the output from building the Dockerfile is as follows:

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进程正在运行(即,该变量在所有情况下都正确地跟踪了实际的shell嵌套,这是只是有时候运行的shell少于预期)。

Finally, the pstree output is interesting because it shows how there is actually no other bash process running at the respective points (i.e. the variable tracks the actual shell nesting correctly in all of the cases, it is just that sometimes there are less shells running than expected).

这篇关于Bash实例未嵌套在Dockerfile`RUN`中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆