Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 从另一个命令获取某些环境变量后,在远程主机上运行的docker容器中运行任意命令_Bash_Shell_Docker_Ssh - Fatal编程技术网

Bash 从另一个命令获取某些环境变量后,在远程主机上运行的docker容器中运行任意命令

Bash 从另一个命令获取某些环境变量后,在远程主机上运行的docker容器中运行任意命令,bash,shell,docker,ssh,Bash,Shell,Docker,Ssh,为了说明我正在尝试做什么,这是我到目前为止使用的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 ) /b

为了说明我正在尝试做什么,这是我到目前为止使用的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""'
因此,让我们分解长命令:
我正在进入一个主机,在那里我运行一个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\u DOCKER\u NAME
中,您只需运行:

docker exec -it $CONTAINER_DOCKER_NAME ...
这将
docker
命令简化为:

docker exec -it $CONTAINER_DOCKER_NAME \
  /bin/sh -c "FOO=\$BAR $COMMAND"
注意我们是如何在
$BAR
中转义
$
的,因为我们需要它 在容器内部解释,而不是由当前shell解释。 现在,我们只需要安排通过
ssh
运行这个。有一对 解决办法。我们可以确保保护地球上的一切 命令行针对额外级别的shell扩展,如 这:

我们需要将整个命令用双引号括起来,这意味着 需要在命令中转义任何引号(我们不能使用单引号) 引号,因为我们实际上想要展开变量
$CONTAINER\u DOCKER\u NAME
本地)。我们将失去一个级别的
\
扩展,因此我们的
\$BAR
成为
\\$BAR

如果您的命令不是交互式的,您可以将其减少一点 通过将脚本管道化到bash而不是将其包含在 命令行,如下所示:

ssh user@$MY_IP docker exec -i $CONTAINER_DOCKER_NAME /bin/sh <<EOF
  FOO=\$BAR $COMMAND
EOF

ssh user@$MY\u IP docker exec-i$CONTAINER\u docker\u NAME/bin/sh我认为我们可以简化您的命令

首先,这里不需要使用
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\u DOCKER\u NAME
中,您只需运行:

docker exec -it $CONTAINER_DOCKER_NAME ...
这将
docker
命令简化为:

docker exec -it $CONTAINER_DOCKER_NAME \
  /bin/sh -c "FOO=\$BAR $COMMAND"
注意我们是如何在
$BAR
中转义
$
的,因为我们需要它 在容器内部解释,而不是由当前shell解释。 现在,我们只需要安排通过
ssh
运行这个。有一对 解决办法。我们可以确保保护地球上的一切 命令行针对额外级别的shell扩展,如 这:

我们需要将整个命令用双引号括起来,这意味着 需要在命令中转义任何引号(我们不能使用单引号) 引号,因为我们实际上想要展开变量
$CONTAINER\u DOCKER\u NAME
本地)。我们将失去一个级别的
\
扩展,因此我们的
\$BAR
成为
\\$BAR

如果您的命令不是交互式的,您可以将其减少一点 通过将脚本管道化到bash而不是将其包含在 命令行,如下所示:

ssh user@$MY_IP docker exec -i $CONTAINER_DOCKER_NAME /bin/sh <<EOF
  FOO=\$BAR $COMMAND
EOF

ssh user@$MY_IP docker exec-i$CONTAINER_docker_NAME/bin/sh多亏了larsks的精彩解释,我的最后一行代码是:

ssh -i $ECS_SSH_KEY ec2-user@$EC2_IP -t "bash -c \"docker exec -it \$( docker ps -a -q -f name=$CONTAINER_DOCKER_NAME | head -n 1 ) /bin/sh -c \\\"eval \\\\\\\$(AWS_ENV_PATH=/\\\\\\\$ENVIRONMENT /bin/aws-env) && $COMMAND\\\"\""
所以基本上你把所有东西都用双引号括起来,然后在里面用双引号,因为我们需要一些变量,比如主机的
$DOCKER\u CONTAINER\u NAME
。转义引号和您使用的$符号\。
但是因为我们有多个级别的shell(主机、服务器、容器),所以我们还需要使用多个级别的转义。因此,第一级是\$,它将保护变量(或shell命令,如
docker ps
)不是在主机上运行,而是在服务器上运行。
那么下一级逃逸是7次\。every\向右转义字符,因此最后它在第二级(服务器)上是
\\\$
,在第三级(容器)上是
\$
。这样可以确保在容器中而不是在服务器上计算变量。
双引号的原理是一样的。
\“
之间的所有内容都在第二级运行,而
\\”
之间的所有内容都在第三级运行。

多亏拉尔克斯的精彩解释,我的最后一句话是:

ssh -i $ECS_SSH_KEY ec2-user@$EC2_IP -t "bash -c \"docker exec -it \$( docker ps -a -q -f name=$CONTAINER_DOCKER_NAME | head -n 1 ) /bin/sh -c \\\"eval \\\\\\\$(AWS_ENV_PATH=/\\\\\\\$ENVIRONMENT /bin/aws-env) && $COMMAND\\\"\""
所以基本上你把所有东西都用双引号括起来,然后在里面用双引号,因为我们需要一些变量,比如主机的
$DOCKER\u CONTAINER\u NAME
。转义引号和您使用的$符号\。
但是因为我们有多个级别的shell(主机、服务器、容器),所以我们还需要使用多个级别的转义。因此,第一级是\$,它将保护变量(或shell命令,如
docker ps
)不是在主机上运行,而是在服务器上运行。
那么下一级逃逸是7次\。每个\转义字符