通过SSH执行远程命令时如何让表达式在远端求值并获取交互shell
问题根源
第一种写法失败原因
你用双引号包裹SSH的远程命令参数时,本地Shell会提前执行命令替换,$(docker ps | grep 'some' | awk '{ print $1 }')这段实际是在你的本地机器运行,拿到的是本地的容器ID,传到远端自然无法正确匹配。
第二种heredoc写法失败原因
docker exec -it需要交互式伪终端才能正常运行,而当你用heredoc向SSH重定向标准输入时,SSH默认检测到stdin不是终端,不会分配伪终端,就会抛出你看到的报错。
可行解决方案
方案1:单引号包裹远程命令+强制分配伪终端
直接给SSH加-t参数强制分配伪终端,同时用单引号包裹整个远程命令,让本地Shell不做提前替换,命令完整传到远端再求值:
ssh -A -t username@ip 'sudo docker exec -it "$(docker ps | grep "some" | awk "{ print \$1 }")" python manage.py shell'
注:如果grep可能匹配到多个容器,可在awk前加
| head -n 1固定取第一个匹配的容器ID,避免执行出错。
方案2:修正后的heredoc写法
给SSH加-tt参数强制分配伪终端(双t代表即使stdin不是终端也强制分配),其余逻辑保持不变即可:
ssh -A -tt username@ip <<'EOL' name="$(docker ps | grep 'some' | awk '{ print $1 }')" sudo docker exec -it "$name" python manage.py shell EOL
注:
<<'EOL'的单引号不能省略,否则还是会触发本地Shell的命令提前替换。
内容的提问来源于stack exchange,提问作者him229
相关产品推荐
相关产品推荐

