转义传递给docker run命令的变量中的$

时间:2018-05-03 23:48:30

标签: docker makefile gnu-make variable-expansion

从makefile执行命令时,我无法弄清楚如何转义美元符号以访问docker环境中定义的变量。

这是我设置的最小代表,我正在尝试回应/mypath

define create-test
so-test-$1:
    docker run \
        --rm \
        -t \
        --env SRC="/mypath" \
        ubuntu:xenial \
        /bin/bash -c "$2"
endef


$(eval $(call create-test,1,echo $SRC ))
$(eval $(call create-test,2,echo $$SRC ))
$(eval $(call create-test,3,echo $$$$SRC ))
$(eval $(call create-test,4,echo $$$$$$$$SRC ))

输出

$ make so-test-1
docker run --rm -t --env SRC="/mypath" ubuntu:xenial /bin/bash -c "echo RC "
RC
$ make so-test-2
docker run --rm -t --env SRC="/mypath" ubuntu:xenial /bin/bash -c "echo RC "
RC
$ make so-test-3
docker run --rm -t --env SRC="/mypath" ubuntu:xenial /bin/bash -c "echo $SRC "

$ make so-test-4
docker run --rm -t --env SRC="/mypath" ubuntu:xenial /bin/bash -c "echo $$SRC "
6526SRC

我知道环境变量已设置,因为它显示我是否在容器中调用env

我应该如何转义SRC变量,以便它在docker容器中的shell运行中展开?

1 个答案:

答案 0 :(得分:1)

您感到困惑的原因是您所引用的引用问题与make无关。它与shell有关。

与编写make recipes一样,您应首先确保您可以从shell提示符运行命令,它可以执行您想要的操作。只有在那之后你才应该把它放在食谱中。假设你在shell提示符下运行它:

docker run \
    --rm \
    -t \
    --env SRC="/mypath" \
    ubuntu:xenial \
    /bin/bash -c "echo $SRC"

这不会奏效。为什么不?因为,shell会在调用命令之前扩展双引号内的所有变量。这意味着您的docker命令实际上将其作为参数:

docker run \
    --rm \
    -t \
    --env SRC="/mypath" \
    ubuntu:xenial \
    /bin/bash -c "echo "

因为shell扩展了$SRC变量,该变量是空的(在docker启动之前它不会被设置,但是这个扩展在docker启动之前由shell发生)。

您需要使用单引号来避免shell扩展您的变量:

docker run \
    --rm \
    -t \
    --env SRC="/mypath" \
    ubuntu:xenial \
    /bin/bash -c 'echo $SRC'

现在你应该可以让你的makefile配方按预期工作了。