如何使用 Expect 执行 sudo 命令并在 bash 脚本中发送命令?

如何使用 Expect 执行 sudo 命令并在 bash 脚本中发送命令?

有人能告诉我如何使用 执行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:~$

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

在 Tcl(以及扩展的 expect)中,花括号的作用类似于 shell 的单引号:抑制变量扩展。

对于您可能看不到模式的情况,expect 的多模式形式很有用。该exp_continue语句本质上在 expect 中“循环”,以便您可以发送密码并继续等待提示。由于没有与提示模式相关的操作,因此控制权从 expect 命令传递到下一个命令。

我建议你将其保存为单独的脚本。第一行应该是

#!/usr/bin/expect -f

如果要嵌入 shell 脚本:

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

请注意第一个“END”周围的引号——它具有单引号引用整个此处文档的效果,因此您不必担心 shell 解释 Expect 变量

答案2

我想分享我的脚本。我在我的系统上试过了。运行良好。

#!/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

尝试使用“interact”命令来结束它,它应该可以工作。

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

答案4

我认为您可能需要在引号内使用反斜杠。否则expect认为命令在“awk”后结束:

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

相关内容