您可以在 bash 脚本中使用 ssh 嵌套远程调用吗?

您可以在 bash 脚本中使用 ssh 嵌套远程调用吗?

我遇到了一个奇怪的问题,Computer A可以看到Computer BComputer B可以看到Computer C,但是Computer A可以不是Computer C

我想制作一个可以在其上运行的 bash 脚本,A该脚本将调用 上的任意命令C,但我似乎无法使双引号正常工作。这个想法是:

AMB_CMD='source eniron.dat; cd path/to/code/; make clean all'
ssh -t username@ComputerB "ssh -t username@ComputerC "$AMB_CMD""

我认为解决要运行的内容B就能解决这个问题,如下所示:

AMB_CMD='source eniron.dat; cd path/to/code/; make clean all'
B_CMD=ssh -t username@ComputerC "$AMB_CMD"
ssh -t username@ComputerB "$B_CMD"

但我仍然遇到问题。

答案1

据我所知,不需要引用实际命令。

ssh username@ComputerB ssh username@ComputerC make clean all

或者,

ssh -J username@ComputerB username@ComputerC make clean all

这将用作ComputerB连接到 的跳转主机ComputerC

使用 OpenSSH 7.3+,配置选项ProxyJump允许您在以下位置配置跳转主机~/.ssh/config

Host ComputerC
    User username
    ProxyJump username@ComputerB

...所以命令将减少为

ssh ComputerC make clean all

make根据您的问题的实际组成(问题中没有提到错误消息),它可能与在错误的目录中运行有关。要cd在运行之前进入正确的目录,make请使用该实用程序的-C选项:

ssh username@ComputerC make -C path/to/build/dir clean all

另外,如果您想将实际命令存储在变量中,则不要使用单个字符串,bash而应使用数组:

cmd=( make -C "path/to/build/dir" clean all )

ssh ... "${cmd[@]}"

答案2

重要的是要意识到传递给的参数ssh被连接起来组成一个外壳命令行解释为登录外壳远程用户的。

因此,为了能够some-shell-code通过与 B 的 ssh 连接在 C 上运行,您需要为 B 构建一个命令行,以便 B 用户的登录 shell 正确解释它以将其some-shell-code按原样传递给ssh

如果 A 上的当前 shell、B 上用户的登录 shell 和 C 上用户的登录 shell 都是bash相同版本(如果某些代码包含非 ASCII 字符,则使用相同的区域设置),并且$CODE包含bash要在 C 上执行的代码,您可以执行以下操作:

printf -v quoted_CODE %q "$CODE"
ssh B "ssh C $quoted_CODE"

如果您无法确定 B 或 C 上用户的登录 shell 是bash,并且不需要通过 stdin 传递任何信息,您可以简单地执行以下操作:

ssh B ssh C bash <<< "$CODE"

或者如果您知道sshdA 和 B 上允许传入LC_*变量(AcceptEnv LC_*常见于sshd_config):

LC_CODE=$CODE ssh -o SendEnv=LC_CODE B '
  ssh -o SendEnv=LC_CODE C bash -c '\'' eval "$LC_CODE"'\'

相关内容