SSHを介してパスワードで保護された複数のコンピュータにログインして再起動する方法は?

SSHを介してパスワードで保護された複数のコンピュータにログインして再起動する方法は?

SSHを介してパスワードで保護された複数のコンピュータを再起動するbashスクリプトを作成しようとしています。 .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

文字列を一重引用符で囲み、シェルが挿入されるのを防ぎます$server。コード作成方法(TCL)もこの形式を使用して変数を挿入しますが、expectTCLコードでは$serverこの形式を使用しません。set server ...したがって、シェルがそれを挿入せず、TCLがそれを設定しないため、エラーが発生します。 1つの方法は、TCL式を二重引用符で囲み、シェルがシェル$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コード内のすべての項目をエスケープする必要があることを意味します。これは、特にコマンドが長く複雑になるにつれて急速に醜くなり、デバッグが困難になる可能性があります。

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

別のオプションは、パラメータをTCL変数として読み取ることです。しかし残念ながら、-cフラグコードはexpect パラメータリストにアクセスできません。これは、パラメータリストがTCLで利用可能になる前にchar *argv[]コードが実行されるためです。-cしたがって、これをTCL変数として使用するには、$serverスクリプトを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
}

これには、改善されたエラー処理、タイムアウト、より良いシェルプロンプトマッチングなどが必要になる場合があります。

関連情報