web-dev-qa-db-ja.com

bashスクリプトでExpect&sendコマンドでSudoコマンドを実行するにはどうすればよいですか?

Sudoを使用してexpectコマンドを実行する方法を教えてもらえますか?私は以下を試しましたが、これは機能しません。誰か提案をお願いできますか?

set login "sasuke"
set addr "hostname"
set pw "mypasswd"
spawn ssh $login@$addr
expect "$login@$addr\'s password:"
send "$pw\r"
expect "#"
send "output=$(Sudo virsh list --all | awk "/running/{print \$2}" | tail -2); Sudo virsh dominfo $output"
expect "password:"
send "$pw\r"
expect "#"

以下のスクリプトを試したところ、エラーなしで実行されましたが、出力が得られませんでした。スクリプトと実行時の出力は次のとおりです。ここでどこを間違えていますか?

set login "sasuke"
set addr "hostname"
set pw "mypasswd"
spawn ssh $login@$addr
expect "$login@$addr's password:"
send "$pw\r"
expect "#"
send {output=$(Sudo virsh list --all | awk '/running/{print $2}' | tail -2)}
expect {
    password: {send "$pw\r"; exp_continue}
    "#"
}
send {Sudo virsh dominfo "$output"}    ;# don't know if you need quotes there
expect {
    password: {send "$pw\r"; exp_continue}
    "#"
}

実行

sasuke@njob:~$ ./hypr.sh 
spawn ssh sasuke@hostname 
sasuke@hostname's password: 
sasuke@hostname:~$ output=$(Sudo virsh list --all | awk '/running/{print $2}' | tail -10)Sudo virsh dominfo '$output' sasuke@njob:~$
9
sasuke
set login "sasuke"
set addr "hostname"
set pw "mypasswd"
spawn ssh $login@$addr
expect "$login@$addr's password:"
send "$pw\r"
expect "#"
send {output=$(Sudo virsh list --all | awk '/running/{print $2}' | tail -2)}
expect {
    password: {send "$pw\r"; exp_continue}
    "#"
}
send {Sudo virsh dominfo "$output"}    ;# don't know if you need quotes there
expect {
    password: {send "$pw\r"; exp_continue}
    "#"
}

Tcl(および拡張機能では、expect)では、中括弧はシェルの単一引用符のように機能し、変数の展開を禁止します。

Expectのマルチパターン形式は、パターンが表示されない場合に役立ちます。 exp_continueステートメントは、基本的に期待内で「ループ」するため、パスワードを送信してプロンプトを引き続き期待できます。プロンプトパターンに関連付けられたアクションがないため、制御はexpectコマンドから次のコマンドに渡されます。

これを別のスクリプトとして保存することをお勧めします。最初の行は

#!/usr/bin/expect -f

シェルスクリプトに埋め込む場合:

#!/bin/sh
expect <<'END'
   # code as above
END

最初の「END」を囲む引用符に注意してください。これは、ヒアドキュメント全体を単一引用符で囲む効果があるため、シェルがExpect変数を解釈することを心配する必要はありません。

10
glenn jackman

スクリプトを共有したいと思います。私のシステムでこれを試しました。これはうまく機能しています。

#!/usr/bin/expect
set username "myname"
set password "mypasswd"
set hosts "hostname"
foreach line [split $ip \n] {
spawn ssh -o StrictHostKeyChecking=no $username@$hosts
expect "$username@$hosts's password:"
send -- "$password\n"
expect "$"
send -- "Sudo virsh list|awk '{print \$2}'|grep 'inmobi' >vm.list; for Host in `cat vm.list`; do Sudo virsh dominfo \$Host >> vm.info; done\n"
expect "$"
send -- "$password\n"
expect "$"
send -- "exit\n"
3
sasuke

引用符内の引用符をバックスラッシュする必要があるかもしれません。それ以外の場合、expectは、コマンドが「awk」の後に終了したと見なします。

send "output=$(Sudo virsh list --all | awk \"/running/{print \$2}\" | tail -2); Sudo virsh dominfo $output"
0
Paul

動作するはずの「対話」コマンドで終了してみてください。

spawn ssh -l $username $ip -p $sshport
sleep 5
expect "password:"
send "$pass\r"
interact
0
Ravan