我从 Solaris 文档中获得了这个技巧,用于将 ssh
公钥复制到远程主机。
注意:ssh-copy-id
在 Solaris 上不可用
$ cat some_data_file | ssh user@host "cat >/tmp/some_data_file; some_shell_cmd"
我想调整它来做更多复杂的事情。
具体来说,我希望some_shell_command
是从本地 主机发送到远程 主机的脚本...脚本将与本地键盘交互(例如,当脚本在远程主机上运行时提示用户)。
我尝试了通过 stdin
从多个来源发送多个内容的方法。但是某些在 local shell 中工作的东西在 ssh 上不工作,并且一些东西,例如下面的,根本没有做我想要的:
$ echo "abc" | cat <(echo "def") # echoes: def (I wanted abc\ndef)
$ echo "abc" | cat < <(echo "def") # echoes: def (I wanted abc\ndef)
$ echo "abc" | cat <<-EOF
> echo $(</dev/stdin) #echoes: echo abc (I wanted: abc)
> EOF
# messed with eval for the above but that was a problem too.
@chepner得出结论,在单个 ssh
命令中完成所有这些操作是不可行的。他提出了一个理论上的替代方案,但没有像希望的那样起作用,但经过一些研究和调整后我让它起作用了,并记录了结果并将其发布为这个问题的答案。
如果没有该解决方案,默认情况下必须运行多个 ssh
和 scp
命令需要多次提示输入密码,这是一个主要的拖累。
我不能指望我在多用户环境中编写的脚本的所有用户都配置公钥授权,也不指望他们会忍受不得不一遍又一遍地输入密码。
最佳答案
OpenSSH session 多路复用
即使在使用早期版本的 OpenSSH 时,此解决方案也适用
ControlPersist
选项不可用。 (此答案末尾的工作 bash 示例)
注:OpenSSH 3.9通过“控制主连接”(2005 年)引入了 session 多路复用,但是,直到 OpenSSH 5.6 才引入 ControlPersist
选项(2010 年发布)。
ssh session 多路复用允许脚本进行一次身份验证并在经过身份验证的连接上执行多个 ssh 事务。例如,如果您有一个使用 ssh
、scp
或 sftp
运行多个不同任务的脚本,则每个事务都可以通过 OpenSSH
“控制主 session ”指的是其命名套接字在文件系统中的位置。
以下一次性密码身份验证在运行必须执行多个 ssh 操作的脚本时非常有用,并且希望避免用户不得不多次密码身份验证,并且在以下情况下特别有用公钥身份验证不可行的情况 - 例如不允许,或至少未配置。
我见过的大多数解决方案都需要使用 ControlPersist
告诉 ssh
无限期地或特定秒数保持控制主连接打开。
不幸的是,使用 OpenSSH 5.6 之前的系统没有该选项(其中升级它们可能不可行)。不幸的是,似乎没有太多关于该在线限制的文档或讨论。
阅读旧版本文档后,我发现 ControlPersist
在 ssh
session 多路复用场景中出现较晚。这意味着可能有另一种方法来配置 session 多路复用,而不依赖于它之前的 ControlPersist
选项。
最初尝试从命令行选项而不是 config 参数配置持久 session ,我遇到了 ssh session 过早终止的问题,关闭控制连接客户端 session ,或者,连接保持打开状态( keep ssh control master alive),终端 I/O 被阻塞,脚本会挂起。
下面说明如何完成它。
OpenSSH option ssh flag Purpose ------------------- --------- ----------------------------- -o ControlMaster=yes -M Establishes sharable connection -o ControlPath=path -S path Specifies path of connection's named socket -o ControlPersist=600 Keep shareable connection open 10 min. -o ControlPersist=yes Keep shareable connection open indefinitely -N Don't create shell or run a command -f Go into background after authenticating -O exit Closes persistent connection
ControlPersist form Equivalent Purpose ------------------- ---------------- ------------------------- -o ControlPersist=yes ssh -Nf Keep control connection open indefinitely -o ControlPersist=300 ssh -f sleep 300 Keep control connection open 5 min.
Note: scp
and sftp
implement -S
flag differently, and -M
flag not at all, so, for those commands, the -o option
form is always required.
Sketchy Overview of Operations:
Note: This incomplete example doesn't execute as shown.
ctl=<path to dir to store named socket>
ssh -fNMS $ctl user@host # open control master connection
ssh -S $ctl … # example of ssh over connection
scp -o ControlPath=$ctl … # example of scp over connection
sftp -o ControlPath=$ctl … # example of sftp over connection
ssh -S $ctl -O exit # close control master connection
session 多路复用演示
(尝试一下。您会喜欢的。工作示例 - 仅验证一次):
运行这个脚本可能会比阅读它更快地帮助您理解它,而且它很吸引人。
注意:如果您无法访问远程主机,只需在“Host...?”处输入 localhost。提示你是否想尝试这个演示脚本
#!/bin/bash # This script demonstrates ssh session multiplexing
trap "[ -z "$ctl" ] || ssh -S $ctl -O exit $user@$host" EXIT # closes conn, deletes fifo
read -p "Host to connect to? " host
read -p "User to login with? " user
BOLD="\n$(tput bold)"; NORMAL="$(tput sgr0)"
echo -e "${BOLD}Create authenticated persistent control master connection:${NORMAL}"
sshfifos=~/.ssh/controlmasters
[ -d $sshfifos ] || mkdir -p $sshfifos; chmod 755 $sshfifos
ctl=$sshfifos/$user@$host:22 # ssh stores named socket ctrl conn here
ssh -fNMS $ctl $user@$host # Control Master: Prompts passwd then persists in background
lcldir=$(mktemp -d /tmp/XXXX)
echo -e "\nLocal dir: $lcldir"
rmtdir=$(ssh -S $ctl $user@$host "mktemp -d /tmp/XXXX")
echo "Remote dir: $rmtdir"
echo -e "${BOLD}Copy self to remote with scp:${NORMAL}"
scp -o ControlPath=$ctl ${BASH_SOURCE[0]} $user@$host:$rmtdir
echo -e "${BOLD}Display 4 lines of remote script, with ssh:${NORMAL}"
echo "====================================================================="
echo $rmtdir | ssh -S $ctl $user@$host "dir=$(</dev/stdin); head -4 \$dir/*"
echo "====================================================================="
echo -e "${BOLD}Do some pointless things with sftp:${NORMAL}"
sftp -o ControlPath=$ctl $user@$host:$rmtdir <<EOF
pwd
ls
lcd $lcldir
get *
quit
EOF
关于bash - 为多个命令使用用户/密码*一次*进行身份验证? ( session 多路复用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41786904/