在Shell脚本中设置和使用SSH ControlMaster会话

Har*_*ikk 3 ssh shell

我正在编写一个脚本,其中包含需要在远程服务器上运行的几组命令,并在两者之间进行结果处理。当前,这是通过ssh为每组命令运行来实现的,但是,这每次都需要进行新连接的建立和身份验证,这很慢。

我最近阅读了有关ControlMasterSSH中的选项的信息,这似乎正是我所需要的,即能够通过单个SSH连接运行单独的SSH会话。

但是,我非常不清楚的是我将如何在shell脚本中实现这一目标。例如,我正在考虑像这样构造它:

#!/bin/sh
HOST="$1"

# Make sure we clean up after ourselves
on_complete() {
    kill $ssh_control_master_id
    rm -r "$tmp_dir"
}
trap 'on_complete 2> /dev/null' SIGINT SIGHUP SIGTERM EXIT

tmp_dir=$(mktemp -d "/tmp/$(basename "$0").XXXXXX")
ssh_control_socket="$tmp_dir/ssh_control_socket"

# Setup control master
ssh -o 'ControlMaster=yes' -S "$ssh_control_socket" "$HOST" &
ssh_control_master_id=$!

# Run initial commands
data=$(ssh -S "$ssh_control_socket" "$HOST" 'echo "Foo"')

# Process the data
echo "$data"

# Run some more commands
data=$(ssh -S "$ssh_control_socket" "$HOST" 'echo "Bar"')

# Process the second batch of data
echo "$data"
Run Code Online (Sandbox Code Playgroud)

只是一个简单的示例,可以使您有所了解,但这似乎不是正确的方法,因为运行它可能会导致第二个ssh命令挂起,或者每个命令都将正常运行(创建自己的连接) 。我也不确定如何等待主连接建立,即-我可能正在运行我的实际命令,而远程连接仍在建立。

还要注意的是,一旦控制主机运行,关闭它的正确方法是杀死它和/或删除其套接字?

che*_*ner 5

您的代码看起来不错。我还没有测试过,但是尝试使用主连接的第一个过程可能应该阻塞,直到成功建立主连接为止。您可以使用该-N选项来避免在主连接上运行伪造的shell:

ssh -N -o 'ControlMaster=yes' -S "$ssh_control_socket" "$HOST" &
Run Code Online (Sandbox Code Playgroud)

ssh所有下级会话完成后,只需终止该进程就可以了。

  • 如果您使用 `-f` 而不是 & 符号来后台 SSH ControlMaster,那么它也将与基于密码的身份验证兼容。否则,它将进入后台,提示输入密码,然后超时。 (3认同)
  • +1 @billyw 建议使用 `-f` 而不是 & 符号。`ssh -f` 命令将阻塞,直到建立连接,因此您不会像使用 & 符号那样出现任何竞争条件。您可以使用“-O check”确保主连接仍然存在,并使用“-O exit”在完成后终止主连接。 (2认同)