bash - 从另一个命令获取一些环境变量后,在远程主机上运行的 docker 容器中运行任意命令
问题描述
为了展示我正在尝试做的事情,这是我目前拥有的 bash 脚本的一部分:
COMMAND="${@:1}"
CONTAINER_DOCKER_NAME=this-value-is-computed-prior
MY_IP=this-ip-is-computed-prior
ssh user@$MY_IP -t 'bash -c "docker exec -it $( docker ps -a -q -f name='$CONTAINER_DOCKER_NAME' | head -n 1 ) /bin/sh -c "eval $(echo export FOO=$BAR) && $COMMAND""'
因此,让我们分解一下长命令:
我正在 ssh 进入一个运行 bash 的主机,该 bash 使用它来获取正确的容器,docker ps
然后我docker exec
在容器中运行一个 shell 来加载一些我$COMMAND
需要工作的环境变量。需要注意的是,$BAR
应该是容器内BAR
变量的值。
所以这就是我试图在理论上完成的事情。但是,无论我如何设置大括号、引号或转义字符,在运行它时 - 我总是遇到问题,要么是 shell 语法不正确,要么它没有运行正确的命令(特别是当命令有多个参数时)或者它加载来自我的本地桌面或远程主机的值,而不是来自容器的值。$BAR
这甚至可以用一个单一的外壳单衬里吗?
解决方案
我认为我们可以大大简化您的命令。
首先,这里不需要使用eval
,也不需要&&
操作符:
/bin/sh -c "eval $(echo export FOO=$BAR) && $COMMAND"
反而:
/bin/sh -c "FOO=$BAR $COMMAND"
这将环境变量设置FOO
为
$COMMAND
.
接下来,您不需要这个复杂的docker ps
表达式:
docker ps -a -q -f name="$CONTAINER_DOCKER_NAME"
Docker 容器名称是唯一的。如果你有一个容器名称存储在 中$CONTAINER_DOCKER_NAME
,你可以运行:
docker exec -it $CONTAINER_DOCKER_NAME ...
这将docker
命令简化为:
docker exec -it $CONTAINER_DOCKER_NAME \
/bin/sh -c "FOO=\$BAR $COMMAND"
请注意我们是如何在其中转义的$
,$BAR
因为我们希望在容器内解释它,而不是通过我们当前的 shell。现在我们只需要安排通过ssh
. 有几个解决方案。我们可以确保保护命令行上的所有内容免受额外级别的 shell 扩展,如下所示:
ssh user@$MY_IP "docker exec -it $CONTAINER_DOCKER_NAME \
/bin/sh -c \"FOO=\\\$BAR $COMMAND\""
我们需要将整个命令用双引号括起来,这意味着我们需要对命令内的任何引号进行转义(我们不能使用单引号,因为我们实际上想在
$CONTAINER_DOCKER_NAME
本地扩展变量)。我们将失去一层
\
扩展,所以我们的\$BAR
变为\\\$BAR
.
如果您的命令不是交互式的,您可以通过将脚本传送到 bash 而不是将其包含在命令行中来减少麻烦,如下所示:
ssh user@$MY_IP docker exec -i $CONTAINER_DOCKER_NAME /bin/sh <<EOF
FOO=\$BAR $COMMAND
EOF
这简化了将事物传递到容器外壳所需的引用和转义。
推荐阅读
- jquery - 来源已被 CORS 策略阻止 对预检请求的响应未通过访问控制检查
- python - 如何在熊猫数据框中用不同颜色为布尔值着色
- django - Django ViewFlow:基于验证导航步骤
- python - 在python中创建一个附加到进程生命周期的文件
- python - 在 python 中创建“.t7”火炬文件
- vectorization - 如何理解 icc 编译器优化报告中的加速?
- splunk - 搜索在字段中包含某些字符串的所有字段
- php - 为什么 PHP 在我的 .html 页面中不再正确解析?
- symfony - Symfony 3.4 部署程序由于共享文件夹的权限被拒绝而失败
- python - Scrapy-Splash:无法使用 scrapinghub/splash:latest 作为基础镜像运行 docker 容器