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

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

我正在尝试编写一个 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

我该如何做而不使用‘-f’?

答案1

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

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

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

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

由于您的示例已经将 SSH 远程命令指定为参数,因此您实际上可以将带引号的字符串延续到多行:

ssh myserver "
  cd somedir &&
  if ./something --check; then
    ./something --update
  fi
  echo 'Done, exiting ssh'
"
echo "Back home"

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

echo "cd foo && ./something" | ssh myserver

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

ssh myserver <<< "cd foo && ./something"

(这可能看起来类似于普通命令ssh myserver "cd foo..",但功能不同——在原始命令中,命令作为单独的“命令”字段发送,而在此示例中,该字段保持为空,命令作为输入(stdin)到 shell。

因此,这只适用于那些本身不需要用户输入的远程命令——如果需要,它们最终会将后续命令读取为它们的输入……)

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

ssh myserver <<EOF
cd foo
./frob --output=\$USER.out
echo "Remote command done"
EOF
echo "ssh exited, we're back"

最后,在后台运行ssh(使用远程 shell 等待输入)并逐步提供输入的方法,特别是 Bashcoproc或通用命名管道,但在几乎所有情况下,它们仅添加过程的复杂性。

相关内容