使用不同的交换机执行多个 ssh 命令

使用不同的交换机执行多个 ssh 命令

我有一个 bash 脚本,用于从远程计算机(我无法控制)复制两个文件,存储在需要访问的路径中root。这里是:

ssh administrator@host "mkdir ${DIR}"
ssh -t administrator@host "sudo su - root -c 'cp /path/for-root-only/data1/${FILENAME} ${DIR}/'"
ssh administrator@host "mv ${DIR}/${FILENAME} ${DIR}/data1-${FILENAME}"
ssh -t administrator@host "sudo su - root -c 'cp /path/for-root-only/data2/${FILENAME} ${DIR}/'"
scp administrator@host:$DIR/{${FILENAME},data1-${FILENAME}} .
ssh administrator@host "rm -r ${DIR}"

该脚本多次提示输入相同的密码。我尝试通过此处的文档合并所有命令,如下所示ssh -t

ssh -t administrator@host << EOF
    mkdir ${DIR}
    sudo su - root -c 'cp /path/for-root-only/data1/${FILENAME} ${DIR}/'
    mv ${DIR}/${FILENAME} ${DIR}/data1-${FILENAME}
    sudo su - root -c 'cp /path/for-root-only/data2/${FILENAME} ${DIR}/'
EOF
scp administrator@host:$DIR/{${FILENAME},data1-${FILENAME}} .
ssh administrator@host "rm -r ${DIR}"

但有这样的警告:

伪终端不会被分配,因为 stdin 不是终端。

我想问是否有正确的方法来编写该脚本以尽量减少密码提示的次数

答案1

打开一次 SSH 连接,然后使用它。 OpenSSH 的这一功能称为主连接。看使用已建立的 SSH 通道

ssh_control_socket="$(mktemp)"
ssh -o ControlPath="$(ssh_control_socket)" -o ControlMaster=yes -o ControlPersist=yes administrator@host "mkdir ${DIR}"
# other commands using ssh (ssh, scp, rsync, …): pass the same ControlPath option
ssh -o ControlPath="$(ssh_control_socket)" -t administrator@host "…"
rsync -e "ssh -o 'ControlPath=$(ssh_control_socket)'" …
ssh -o ControlPath="$(ssh_control_socket)" administrator@host -O exit
rm -f "$(ssh_control_socket)"

令人烦恼的是,您需要在每个 SSH 调用上显式传递一个选项(它是用于在每个调用和进行实际连接的原始 SSH 客户端ControlPath之间进行通信的文件的名称)。ssh这里我传递了一个显式的套接字名称,以便脚本是独立的。如果依赖~/.ssh/config是可以接受的,那么将此行添加到您的~/.ssh/config

ControlPath ~/.ssh/%l_%h_%p_%r.multiplex

这使得每个 SSH 客户端都能够检查是否存在现有连接。除非有监听主连接,否则该功能实际上不会被使用,您仍然需要在第一个连接上传递-o ControlMaster=yes(或-M简称),即您的脚本可以是

# Open the shared connection
ssh -M -o ControlPersist=yes administrator@host :
# … all SSH-relying commands in their basic form, they will go via the shared connection …
# Close the shared connection
ssh -O exit administrator@host

答案2

你不需要这样做这里文档(这就是该<<内容的作用)。

你可以简单地做ssh remotehost "command1; command2 ; command3"

例如

% ssh localhost "date ; uptime ; echo hello"
sweh@localhost's password: 
Tue Jul 19 08:07:48 EDT 2016
 08:07:48 up 15 days, 31 min,  3 users,  load average: 0.33, 0.33, 0.40
hello

然而scp,不会轻易地以这种方式合并。

所以你可能想考虑使用公钥认证而不是密码身份验证(也称为“ssh 密钥”)。通常这样的事情就是这样自动化的。

相关内容