如何创建在执行远程命令后退出 ssh 会话的 shell 脚本

pbu*_*eit 1 ssh unix bash macos

我正在尝试编写一个 bash 脚本来编译一些代码并将其部署到远程服务器。到目前为止,我一直在努力弄清楚如何让脚本退出 ssh 会话。我以为我可以只使用“exit”,但似乎退出脚本而不实际关闭 ssh 会话。在 ssh 命令中使用“-f”标志是我见过的另一个选项,但这限制了我可以做的事情而不会让我的脚本变得混乱。-f 要求将所有远程命令塞进对 ssh 的一次调用中。对于一两个命令来说这很好,但对于更复杂的操作来说会变得混乱。

是否还有其他选项允许在 shell 脚本中启动和关闭 ssh 会话?

作为参考,这里有一个快速示例脚本:

#!/bin/bash
echo 'starting a thing...'
mkdir folderA
ssh -f messagecenter-dev -p 22001 'uptime; free -m | cat /proc/loadavg'
cd folderA
echo 'I did a thing!'
exit
Run Code Online (Sandbox Code Playgroud)

我该如何在不需要使用“-f”的情况下做到这一点?

use*_*686 5

\n

-f 要求将所有远程命令塞进对 ssh 的一次调用中

\n
\n

这不是 -f 所需要的。无论如何你都需要这样做。

\n

脚本不模拟键盘输入;他们启动程序并等待这些程序完成。如果您没有预先指定命令而是让它打开交互式 shell,则对于 SSH 连接 \xe2\x80\x93 使用什么选项并不重要,那么脚本的其余部分不会像键盘输入一样进入 SSH 会话;该脚本只是暂停在那里,等待 SSH 退出,而脚本的其余部分始终在本地运行。

\n

因此,您需要预先提供整个命令。它可以通过多种不同的方式通过多行来完成,但您仍然需要将其识别为使用指定输入运行一个命令的单个“单元”,而不是模拟键入的行。

\n

由于您的示例已将 SSH 远程命令指定为参数,因此您实际上可以在多行中继续引用的字符串:

\n
ssh myserver "\n  cd somedir &&\n  if ./something --check; then\n    ./something --update\n  fi\n  echo \'Done, exiting ssh\'\n"\necho "Back home"\n
Run Code Online (Sandbox Code Playgroud)\n

或者,如果您不指定参数,则可以将命令发送到远程 shell 的输入(shell 将以非交互模式运行并且不会显示提示)。一个基本的单行示例是:

\n
echo "cd foo && ./something" | ssh myserver\n
Run Code Online (Sandbox Code Playgroud)\n

或者,在 Bash 中(不是普通的 sh):

\n
ssh myserver <<< "cd foo && ./something"\n
Run Code Online (Sandbox Code Playgroud)\n

(这可能看起来与普通文本类似ssh myserver "cd foo..",但功能不同 \xe2\x80\x93 在原始文件中,命令作为单独的“命令”字段发送,而在本例中该字段保持为空,命令作为输入发送(stdin )到外壳。

\n

因此,这仅适用于本身不需要用户输入 \xe2\x80\x93 的远程命令,如果需要,它们最终将读取后续命令作为输入...)

\n

在上面的两个例子中,都"quoted command"可以是多行的。指定多行的另一种方法是“heredoc”(它遵循与双引号字符串相同的引用/转义规则):

\n
ssh myserver <<EOF\ncd foo\n./frob --output=\\$USER.out\necho "Remote command done"\nEOF\necho "ssh exited, we\'re back"\n
Run Code Online (Sandbox Code Playgroud)\n

最后,有一些方法可以在后台运行ssh(远程 shell 等待输入)并增量地为其提供输入,特别是 Bashcoproc或通用命名管道,但在几乎所有情况下,它们只会增加过程的复杂性。

\n