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

时间:2014-03-14 17:31:04

标签: shell ssh

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

我最近读到了SSH中的ControlMaster选项,这看起来正是我所需要的,即能够通过单个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"

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

另外在相关的说明中,关闭控制主机一旦运行,正在杀死它和/或删除其套接字的正确方法是什么?

1 个答案:

答案 0 :(得分:4)

您的代码看起来很好。我还没有对它进行测试,但尝试使用主连接的第一个进程可能会阻塞,直到主连接实际成功建立。您可以使用-N选项来避免在主连接上运行虚假shell:

ssh -N -o 'ControlMaster=yes' -S "$ssh_control_socket" "$HOST" &

一旦完成所有下属会话,简单地终止ssh进程就完全没问题了。