如何使用bash脚本中的Expect和send命令执行sudo命令?


10

有人可以让我知道如何执行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:~$

Answers:


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

在Tcl中(大胆地期望),花括号的作用类似于外壳的单引号:禁止变量扩展。

期望的多模式形式对于您可能看不到模式的情况很有用。该exp_continue语句实际上在期望值内“循环”,因此您可以发送密码并继续期望该提示。由于没有与提示模式关联的操作,因此控制权从Expect命令传递到下一个命令。

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

#!/usr/bin/expect -f

如果要嵌入外壳脚本中:

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

请注意第一个“ END”周围的引号-它具有单引号引用整个here-document的作用,因此您不必担心shell会解释Expect变量


嗨,格伦,脚本执行没有错误,但是我看不到脚本的输出。我在脚本中做错了什么吗?如果是,请让我知道我将输出保存在单独的文件中。这是我正在执行的脚本sasuke @ njob:〜$ ./hypr.sh spawn ssh sasuke @ hostname sasuke @ hostname的密码:sasuke @ hostname:〜$ output = $(sudo virsh list --all | awk'/ running / {print $ 2}'| tail -10)sudo virsh dominfo'$ output'sasuke @ njob:〜$
sasuke

您无法在评论中发布代码,请在您的问题中添加代码
glenn jackman 2013年

哦,对此我感到抱歉。谢谢我做到了。请帮帮我。
佐助2014年

不知道 添加exp_internal 1到脚本顶部并阅读详细的输出。
glenn jackman

3

我想分享我的脚本。我在系统上尝试过。这很好。

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

1

尝试以应该起作用的“交互”命令结束它。

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

0

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

send "output=$(sudo virsh list --all | awk \"/running/{print \$2}\" | tail -2); sudo virsh dominfo $output"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.