shell 脚本中的参数扩展取消引用环境变量

Dereference environment variable on parameter expansion in shell script

我正在尝试使用参数扩展 $@ 取消引用环境变量的值,但它似乎不起作用。

我需要使用某些参数调用 shell 脚本。参数列表包含环境变量,环境变量应该出现在要执行 shell 脚本的位置。我事先不知道命令列表,所以我使用 $@ 扩展这些命令列表。但是,该脚本无法取消引用环境变量的值。

可以按如下方式完成解释我的问题的最小设置。

FROM alpine:3.10

ENV MY_VAR=production

WORKDIR /app

COPY run.sh .

ENTRYPOINT [ "sh", "run.sh" ]
#!/bin/sh

echo "Value of MY_VAR is" $MY_VAR

echo "Begin"

$@

echo "Done"

我可以使用 docker build . -t env-test 构建图像。当我 运行 它使用 docker run env-test:latest 'echo $MY_VAR' 时,我得到以下输出。

Value of MY_VAR is production
Begin
$MY_VAR
Done

虽然我期望的输出是:

Value of MY_VAR is production
Begin
production
Done

旁注:实际上我正在尝试 运行 它使用如下的撰写文件:

version: '3'

services:
  run:
    image: env-test:latest
    command: echo $$MY_VAR

但它再次给了我类似的结果。

首先,$@ 它只会打印参数的数量

#!/bin/sh

echo "Value of MY_VAR is" $MY_VAR

echo "Begin"

$@

echo "Done"

$@ = 将所有参数存储在字符串列表中

$* = 将所有参数存储为一个字符串

$# = 存储参数个数

What does $@ mean in a shell script?

第二件事,当运行下面的命令

docker run env-test:latest 'echo $MY_VAR'

它将在主机系统而不是容器中寻找 $MY_VAR。

要访问容器环境,您必须将它们作为 -e MY_VAR=test 传递,而不是作为参数传递给 docker 运行 命令,该命令将在主机的 ENV 中。

docker run -e MY_VAR=test env-test:latest

因此 MY_VAR 的值将是 test 而不是 production

调试 docker run

的参数
export MY_VAR2="value_from_host"

现在运行

docker run env-test:latest "echo $MY_VAR2"

所以该值将 value_from_host 因为这些参数是从主机中选择的。

扩展 eval 方法,这是一个简单的 bash 脚本,它将使用 eval 将字符串作为 bash 命令序列求值:

#!/usr/bin/env bash
echo program args:  $@
eval $@

但请注意,eval 伴随着危险:

https://medium.com/dot-debug/the-perils-of-bash-eval-cc5f9e309cae

有更多方法可以给这只猫剥皮:

me@computer:~$ docker run -it --rm ubuntu:20.04 bash -c 'echo $HOSTNAME'
e610946f50c1

在这里,我们在容器内调用bash来处理单引号内的所有内容,因此变量替换and/or扩展不是由您的 shell 应用,但由容器内的 shell 应用。

另一种方法是:

me@computer:~$ cat test.sh
#!/bin/bash

echo $HOSTNAME

me@computer:~$ cat test.sh | docker run -i --rm ubuntu:20.04 bash
62ba950a60fe

在这种情况下,cat 将脚本的内容“推送”到 bash 容器,因此它在功能上等同于我的第一个示例。第一种方法“更干净”,但是如果您有更复杂的脚本、多行变量或其他难以放入单个命令的内容,那么第二种方法是更好的选择。

注意:每个示例中的主机名都不同,因为我使用的是 --rm 选项,它会在容器退出后丢弃它。当您想 运行 容器中的命令但之后不需要保留容器时,这非常有用。