Jak wykonywać polecenia sudo za pomocą funkcji Expect & Send w skrypcie bash?

10

Czy ktoś może mi powiedzieć, jak wykonywać sudopolecenia expect? Próbowałem następujące, ale to nie działa. Czy ktoś może mi zasugerować?

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 "#"

Kiedy wypróbowałem poniższy skrypt, wykonałem go bez błędów, ale nie otrzymałem danych wyjściowych. Oto skrypt i dane wyjściowe po uruchomieniu. Gdzie popełniam błąd?

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}
    "#"
}

Wykonanie

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:~$
sasuke
źródło

Odpowiedzi:

10
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}
    "#"
}

W Tcl (i, co za tym idzie, spodziewaj się), nawiasy klamrowe działają jak pojedyncze cudzysłowy powłoki: hamują ekspansję zmiennej.

Forma typu oczekiwanie na wiele wzorów jest przydatna w przypadku, gdy wzór może nie być widoczny. Theexp_continueOświadczenie zasadzie „pętli” w oczekują więc można wysłać hasło i nadal oczekują szybka. Ponieważ z wzorcem zachęty nie jest związana żadna czynność, sterowanie przechodzi z polecenia expect do następnego.

Polecam zapisać to jako osobny skrypt. Pierwsza linia powinna być

#!/usr/bin/expect -f

Jeśli chcesz osadzić w skrypcie powłoki:

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

Zwróć uwagę na cytaty wokół pierwszego „END” - co powoduje pojedyncze zacytowanie całego dokumentu tutaj, więc nie musisz się martwić, że powłoka interpretuje zmienne Expect

Glenn Jackman
źródło
Cześć Glenn, skrypt działa bez błędów, ale nie widzę danych wyjściowych skryptu. Czy robię coś złego w skrypcie. Jeśli tak, proszę dać mi znać, że zapisuję dane wyjściowe w osobnym pliku. oto skrypt, który wykonuję sasuke @ njob: ~ $ ./hypr.sh spawn ssh sasuke @ nazwa hosta sasuke @ nazwa hosta hasło: sasuke @ nazwa hosta: ~ $ output = $ (sudo virsh list --all | awk '/ running / {print $ 2} '| tail -10) sudo virsh dominfo' $ output 'sasuke @ njob: ~ $
sasuke
Nie możesz pisać kodu w komentarzach, dodaj go w swoim pytaniu
glenn jackman
przepraszam za to. Dzięki, że to zrobiłem. Proszę pomóż mi.
sasuke
Nie wiem Dodaj exp_internal 1na górę skryptu i przeczytaj pełne dane wyjściowe.
glenn jackman
3

Chciałbym podzielić się moim scirptem. Próbowałem tego na swoim systemie. to działa dobrze.

#!/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"
sasuke
źródło
1

Spróbuj zakończyć to poleceniem „interakcji”, które powinno działać.

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

Myślę, że możesz potrzebować odwrotnego ukośnika w cudzysłowie. W przeciwnym razie expectuważa, że ​​polecenie kończy się po „awk”:

send "output=$(sudo virsh list --all | awk \"/running/{print \$2}\" | tail -2); sudo virsh dominfo $output"
Paweł
źródło