shell 脚本中的参数扩展取消引用环境变量
Dereference environment variable on parameter expansion in shell script
我正在尝试使用参数扩展 $@
取消引用环境变量的值,但它似乎不起作用。
我需要使用某些参数调用 shell 脚本。参数列表包含环境变量,环境变量应该出现在要执行 shell 脚本的位置。我事先不知道命令列表,所以我使用 $@
扩展这些命令列表。但是,该脚本无法取消引用环境变量的值。
可以按如下方式完成解释我的问题的最小设置。
- Docker 文件
FROM alpine:3.10
ENV MY_VAR=production
WORKDIR /app
COPY run.sh .
ENTRYPOINT [ "sh", "run.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
选项,它会在容器退出后丢弃它。当您想 运行 容器中的命令但之后不需要保留容器时,这非常有用。
我正在尝试使用参数扩展 $@
取消引用环境变量的值,但它似乎不起作用。
我需要使用某些参数调用 shell 脚本。参数列表包含环境变量,环境变量应该出现在要执行 shell 脚本的位置。我事先不知道命令列表,所以我使用 $@
扩展这些命令列表。但是,该脚本无法取消引用环境变量的值。
可以按如下方式完成解释我的问题的最小设置。
- Docker 文件
FROM alpine:3.10
ENV MY_VAR=production
WORKDIR /app
COPY run.sh .
ENTRYPOINT [ "sh", "run.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
选项,它会在容器退出后丢弃它。当您想 运行 容器中的命令但之后不需要保留容器时,这非常有用。