当我跑步时:
ssh [email protected] bash -c "/home/devops_staging/deployJob.sh example"
我遇到以下错误:
/home/devops_staging/deployJob.sh: line 4: $1: unbound variable
如果我在没有该bash -c
部件的情况下运行它,它会按预期工作。
ssh [email protected] /home/devops_staging/deployJob.sh example
deploy success
为什么会出现这种情况?
这是非常出乎意料的,因为我似乎记得总是使用这种语法,ssh ... bash -c "commands param1 param2"
没有任何问题。
有问题的脚本非常简单,我在第 4 行所做的就是分配一个变量$1
(这应该是第一个参数):
#!/usr/bin/env bash
set -euo pipefail
CI_PROJECT_NAME="$1"
...
调试时bash -x -c ...
我看到以下可疑的行:
+ '[' -z '' ']'
+ return
+ case $- in
+ return
+ /home/devops_staging/deployJob.sh
/home/devops_staging/deployJob.sh: line 4: $1: unbound variable
我认为这是以下问题的重复:ssh command withquotes。已经注意到了,但作者在这里指出:
因此,这个答案试图在当前问题中使用的代码的上下文中具体解释该问题。
从这个链接问题的良好答案中最重要的信息是:
如果你在本地运行
那么参数
ssh
被识别为要传递到远程端的代码将是:/home/devops_staging/deployJob.sh
,example
。参数串联的字符串将是这将是在远程端运行的 shell 代码。碰巧这就是你想要的字符串。
但如果你在本地运行
那么参数将是:
bash
,-c
,/home/devops_staging/deployJob.sh example
远程 shell 的字符串将是(就好像参数是:
bash
,-c
,/home/devops_staging/deployJob.sh
,example
)并且这不是您想要在远程端运行的 shell 代码。这里example
不属于选项参数-c
(它就像另一个问题sh
中的第二个)。如果您想要这个字符串作为远程代码:
那么最简单的方法是将字符串
ssh
作为单个参数传递给本地:单引号参数包含要传递给远程 SSH 服务器启动的 shell 的所有 shell 代码。
请注意,您甚至可以在本地执行此操作:
其中双引号(对于远程 shell)属于两个单独的本地参数,远程 shell 的结果字符串将是相同的。
请注意有多少工具解释和消化该命令,直到您(远程)中的代码
deployJob.sh
运行:本地 shell 执行分词、删除引号(通常还有其他一些操作)。结果
ssh
可能会得到一个或多个参数,它会将其解释为要传递到远程端的代码。ssh
将这些参数与中间的空格连接起来,以便将单个字符串传递到远程 shell。远程 shell 自行执行分词、删除引号(以及通常的其他一些操作)。它运行一些命令。
如果命令是
bash -c …
另一个(远程)shell 将解析作为选项参数的代码-c
。分词、删除引号和其他操作也将由该 shell 执行。如果
deployJob.sh
包含一个正常的 shebang (或 none),那么将会有另一个(远程)shell 依次解释该文件。一般来说,在所有先前的工具消化了它们的参数之后,您需要预测并策划哪些工具会获得哪些参数;以及它将传递给下一个工具的参数是什么。您需要设计本地命令,以便最终的工具能够准确地获得您想要的结果。