How to execute sudo commands with Expect & send commands in bash script?
Solution 1:
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}
"#"
}
In Tcl (and, by extension, expect), curly braces act like the shell's single quotes: inhibit variable expansion.
The multi-pattern form of expect is useful for the case where you may not see a pattern. The exp_continue
statement essentially "loops" within the expect so you can send the password and continue to expect the prompt. Since there is no action associated with the prompt pattern, control passes from the expect command to the next one.
I would recommend you save this as a separate script. First line should be
#!/usr/bin/expect -f
If you want to embed in a shell script:
#!/bin/sh
expect <<'END'
# code as above
END
Note the quotes around the first "END" -- that has the effect of single quoting the entire here-document so you don't have to worry about the shell interpreting the Expect variables
Solution 2:
I would like to share my scirpt. I tried this on my system. this is working fine.
#!/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"
Solution 3:
Try to end it with the "interact" command it should work.
spawn ssh -l $username $ip -p $sshport
sleep 5
expect "password:"
send "$pass\r"
interact