在Shell脚本中设置并使用SSH ControlMaster会话
我正在编写一个脚本,其中包含在远程服务器上运行所需的多组命令,并在其间处理结果。目前,这是通过为每一组命令运行在Shell脚本中设置并使用SSH ControlMaster会话,shell,ssh,Shell,Ssh,我正在编写一个脚本,其中包含在远程服务器上运行所需的多组命令,并在其间处理结果。目前,这是通过为每一组命令运行ssh来实现的,但是这需要每次建立一个新的连接并进行身份验证,这很慢 我最近读到了SSH中的ControlMaster选项,这似乎正是我所需要的,即通过单个SSH连接运行单独SSH会话的能力 然而,我非常不清楚的是,我将如何在shell脚本中实现这一点。例如,我想这样构造它: #!/bin/sh HOST="$1" # Make sure we clean up after ourse
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
命令挂起,或者每个命令都会正常运行(创建它们自己的连接)。我也不知道如何等待主连接建立,也就是说,我可能正在运行我的实际命令,而远程连接仍在建立
另一个相关的注意事项是,一旦控制主机运行,关闭它和/或删除它的套接字的正确方法是什么?您的代码看起来很好。我还没有测试它,但是尝试使用主连接的第一个进程可能会阻塞,直到主连接实际成功建立。您可以使用
-N
选项来避免在主连接上运行假外壳:
ssh -N -o 'ControlMaster=yes' -S "$ssh_control_socket" "$HOST" &
在所有下级会话完成后,简单地终止
ssh
进程是非常好的。感谢关于-N
标志的提示,我以前没有注意到这一点!但是,我不清楚在主连接建立之前如何阻止,在ssh
中是否有这样做的功能?我的假设是,如果您使用-S
启动ssh
以请求特定套接字,并且该套接字存在,但主连接尚未完全建立,ssh
将一直阻止,直到建立连接,而不是打开自己的另一个套接字。如果您使用-f
而不是符号作为ssh ControlMaster的后台,那么它也将与基于密码的身份验证兼容。否则,它将返回后台,提示输入密码,然后超时。@billyw建议使用-f
而不是符号。ssh-f
命令将一直阻塞,直到建立连接为止,因此您将不会像使用ampersand一样出现任何竞争条件。您可以使用-O check
确保主连接仍处于活动状态,并使用-O exit
在完成后终止主连接。