如何通过 ssh 登录多台受密码保护的计算机并重新启动它们?

如何通过 ssh 登录多台受密码保护的计算机并重新启动它们?

我正在尝试编写一个 bash 脚本来通过 ssh 重新启动多台受密码保护的计算机。我在 .txt 文件中列出了所有 IP,并希望脚本从那里读取 IP。由于我的 mac 没有 sshpass,所以我一直在弄乱 Expect 命令。有没有办法在没有 sshpass 的情况下做到这一点?

到目前为止我有这个:

#!/bin/bash

for server in 'testreboot.txt'; do
expect -c 'spawn ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 
administrator@$server "sudo shutdown -r now"; expect "Password:"; send 
"password\r"; interact'
done

在 testreboot.txt 中,我只列出了测试机器的 IP 地址。可以吗还是我需要将它分配给一个变量?当我尝试运行它时,我不断收到变量错误。

答案1

您用单引号引用了该字符串;这会阻止 shell 进行插值$server。 TCL(expect编写代码的方式)也使用该形式来插入变量,但您在 TCL 代码中$server没有使用该形式 。set server ...因此会出现错误,因为 shell 没有插入它,TCL 也没有设置它。一种方法是双引号 TCL 表达式,这将允许 shell 在 shell$server变量中进行插值:

$ server=example; expect -c 'puts $server'
can't read "server": no such variable
    while executing
"puts $server"
$ server=example; expect -c "puts $server"
example
$ 

然而,这意味着"TCL 代码中的任何内容都需要进行转义,以防止它们干扰 shell 插值,这可能会很快变得难看并且很难调试,特别是当命令变得更长、更复杂时。

$ server=example; expect -c "puts \"a server named '$server'\""
a server named 'example'
$ 

另一种选择是将参数读入 TCL 变量,但是,唉,-c标志代码expect 无权访问参数列表 因为char *argv[]代码-c在参数列表可供 TCL 使用之前运行。因此,要用作$serverTCL 变量,需要用 TCL 重写脚本:

#!/usr/bin/env expect

set fh [open testreboot.txt r]

while {[gets $fh server] >= 0} {
    spawn -noecho ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 \
       administrator@$server
    expect -ex "Password:"
    send "Hunter2\r"
    expect -ex {$ }
    send "sudo shutdown -r now\r"
    expect -ex "Password:"
    send "Hunter2\r"
    interact
}

这可能需要改进错误处理、超时、更好地匹配 shell 提示符等。

相关内容