在同一个 shell 中执行多个 ssh 命令(以编程方式)

在同一个 shell 中执行多个 ssh 命令(以编程方式)

注意:我正在寻找SSH y解决方案在这里,超过巴什一。

我需要通过 ssh 以编程方式执行一系列命令。有很多方法可以做到这一点,但我找不到任何适合我的约束的方法:

  • 一些命令在 shell 中设置变量。因此,我认为我无法使用多个 shell 来完成这项工作。

  • 其中一些变量是函数,而不是普通值,所以我不认为我可以简单地序列化输出来env“恢复”旧环境。

  • &&我需要分别访问每个命令的 stdout、stderr 和退出代码。这使得使用或链接命令变得很困难;。我相信这也使得使用 变得很困难screen,因为我们无法可靠地判断命令何时完成。

  • 我需要实时访问 stdout、stderr 等,以便我们可以记录输出发生的时间。(我使用“实时”来表示“现在”,而不是“硬实时”或诸如此类的意思)。

更新

为什么我需要单个 bash 会话?因为命令可能会在环境中存储任意变量和函数。例如,运行 是很常见的rvm,这是由先前运行的命令添加的 bash 函数。

为什么我不能使用&&;因为我需要 stdout 和 stderr 或每个单独的命令,而这会将它们混合在一起。

为何我无法使用屏幕?因为我们希望自动运行命令,而不是作为交互式会话的一部分。考虑一下这样做的难度:我必须使用输入表单重定向来运行命令,通过重定向输出,然后将结果 scp 回来。我需要 echo$?来获取退出代码。我无法为 stderr/stdout 加时间戳。我无法使命令超时。而且它会非常容易出错。

答案1

如果你需要能够捕获输出、与 shell 会话交互和/或与 pty 应用程序交互的东西,screen你可以尝试用更高级语言的 SSH 库编写,比如 Ruby 的网络:SSH。它有一点学习曲线,但我相信可以满足您的所有需求。

答案2

我需要分别访问每个命令的 stdout、stderr 和退出代码。这使得使用 && 或 ; 链接命令变得很困难。

好吧,我不知道我是否真的推荐这个,但是你可以编写一个类似这样的 shell 函数:

function prefix ()
(
  PREFIX="$1"
  OUT=''
  while read -r ; do
    OUT="${OUT}${PREFIX}${REPLY}"$'\n'
  done
  echo "$OUT"
)

function run_cmd ()
{
  echo "Running command << $@ >> . . ."
  (
    ( ( "$@" ; echo "\$?: $?" >&3 ) | prefix 'STDOUT: ' >&3 ) 2>&1 \
    | prefix 'STDERR: '
  ) 3>&1
}

然后,如果./foo.sh bar打印出foo\nbar\n标准输出和baz\nbip\n标准错误,并以代码 1 退出,run_cmd ./foo.sh bar则会打印类似以下内容:

Running command << ./foo.sh bar >> . . .
$?: 0
STDOUT: foo
STDOUT: bar
STDERR: baz
STDERR: bip

这应该允许您链接一系列命令,前提是您使用run_cmd它们来执行所有需要 STDOUT/STDERR/退出代码的命令。(但由于命令本身在五层深度的子 shell 中运行,因此您不能使用它来run_cmd运行任何需要设置环境变量以供其他命令使用的命令。希望您没有任何命令两个都给出输出设置变量?

答案3

你已经看过了吗pssh?它涵盖了你的大部分需求,只要发挥一些创造力和想象力,它就可能对你有所帮助:

  • 可以同时向多个服务器发送命令
  • 能够实时输出
  • stdout 和 stderr 可以保存到单独的文件中
  • 报告服务器 Y 上的命令 X 是否成功
  • 可以从 stdin 接收输入并将其发送到服务器
  • 具有可配置的超时

等等...

答案4

我还认为 Kyle 的方法是最有希望的。如果这种方法行不通,您可以编写主脚本,使其进入无限循环,在其中查找命令文件,然后获取命令文件,并以可用于您目的的形式提供 stdout、stderr 和退出代码。

然后,您可以通过备用渠道插入命令文件,可能只是scp  或类似的东西。

相关内容