【问题标题】:expect script to ssh returns invalid command name期望 ssh 的脚本返回无效的命令名称
【发布时间】:2013-04-19 05:20:11
【问题描述】:

我正在尝试编写一个期望脚本,它将 ssh 到服务器,发送 sudo su,然后检查 iptables 状态并将输出放在服务器上的日志文件中。下面是脚本。

1 #!/usr/bin/expect
  2 exp_internal 1
  3 log_user 0
  4 set timeout 10
  5 set password  "******"
  6 
  7 spawn /usr/bin/ssh -l subhasish *.*.*.* -p 10022
  8 
  9 expect {
 10      -re "password: " {send "$password\r"}
 11      -re "$ "  {send "sudo su\r"}
 12      -re "[sudo] password for subhasish:" {send "$password\r"}
 13      -re "# "  {send "service iptables status\r"}
 14        }
 15 set output $expect_out(buffer)
 16 send "exit\r"
 17 puts "$output\r\n" >> output.log

但是在调试模式下运行时,我收到这样的错误;

expect -d testcase
expect version 5.44.1.15
argv[0] = expect  argv[1] = -d  argv[2] = testcase  
set argc 0
set argv0 "testcase"
set argv ""
executing commands from command file testcase
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {24105}
invalid command name "sudo"
    while executing
"sudo"
    invoked from within
"expect {
     -re "password: " {send "$password\r"}
     -re "$ "  {send "sudo su\r"}
     -re "[sudo] password for subhasish:" {send "$password\r"}
 ..."
    (file "testcase" line 9)

不知道我哪里出错了。它说无效的命令名称“sudo”,我猜这是因为期望不理解这些命令。如何绕过它。请帮忙。谢谢。

【问题讨论】:

    标签: expect


    【解决方案1】:

    问题出在这一行

    -re "[sudo] password for subhasish:" {send "$password\r"}
    

    在 Tcl 中(因此在期望中)方括号是命令替换的语法(就像 shell 中的反引号)。因此,您要么需要转义括号,要么使用不同的引号来防止各种扩展:

    -re {[sudo] password for subhasish:} {send "$password\r"}
    

    这带来了一个不同的问题:您是否希望看到这些确切的字符?因为您指示 expect 将其视为正则表达式,而正则表达式中的方括号表示字符类,因此它将匹配单个字符,“s”、“u”、“d”或“o” '。所以你可能需要的是这样的:

    -re {\[sudo\] password for subhasish:} {send "$password\r"}
    

    -ex {[sudo] password for subhasish:} {send "$password\r"}
    

    【讨论】:

    • 我已将 sudo su 期望更改为“subhasish 的密码:”以及您提到的方式,这两种情况都不起作用;使用更新的以下代码,#!/usr/bin/expect -f #! /bin/bash set timeout 60 log_user 1 set host ..*.* set password ****** set user subhasish set logfile output.txt spawn ssh -p 10022 $user@$host expect "*?assword:*" 发送 -- "$password\r" log_user 1 期望 "$" 发送 -- "sudo su\r" 期望 "subhasish 的密码:" 发送 -- "$password\r" 期望 "# " 发送 -- "服务 iptables 状态\r" log_file /home/subhasish/output.log 期望 "#" log_file 发送 -- "exit\r";发送——“退出\r”; 0号出口
    • 手动记录是这样的,[root@localhost subhasish]# ssh -p 10022 subhasish@*.*.*.* subhasish@*.*.*.*'s password: Last login : Mon Apr 29 07:19:52 2013 from ..*.* [subhasish@testhost ~]$ sudo su [sudo] subhasish 的密码:[root@testhost subhasish]#
    • 调试脚本显示它卡在了期望中:期望:does "\r\n上次登录:Mon Apr 29 07:35:36 2013 from ..*.*\ r\r\n\u001b]0;subhasish@testhost:~\u0007" (spawn_id exp4) 匹配 glob 模式“subhasish 的密码:”?否 [subhasish@testhost ~]$ expect: do "\r\n上次登录时间:Mon Apr 29 07:35:36 2013 from ..*.*\r\r\n\u001b]0 ;subhasish@testhost:~\u0007\u001b[?1034h[subhasish@testhost ~]$ " (spawn_id exp4) 匹配全局模式“subhasish 的密码:”?没有
    • 全局模式需要匹配 整个 字符串,因此您需要前导和尾随通配符:expect -gl {*password for subhasish:*}.,此外,这些字符串不会匹配,因为“密码”字样for" 不出现。
    【解决方案2】:

    感谢 Glenn,它现在可以正常工作了。它不起作用的另一个原因是它需要在正常登录和 sudo 登录之间休眠,否则在返回 $ 提示之前发送“sudo su”,供参考,这里是代码,

    #!/usr/bin/expect -f
    #! /bin/bash
    
    set timeout 60
    log_user 1
    set host *.*.*.*
    set password ****** 
    set user subhasish
    set logfile output.txt
    spawn ssh -p 10022 $user@$host
    expect "*?assword:*"
    send -- "$password\r"
    #log_user 1
    sleep 2
    expect "$"
    send -- "sudo su\r"
    expect -gl {*password for subhasish:*}
    send -- "$password\r"
    expect "#"
    send -- "service iptables status\r"
    log_file /home/subhasish/output.log
    expect "#"
    log_file
    send -- "exit\r";
    send -- "exit\r";
    exit 0
    

    【讨论】:

    • 等待提示很有帮助。
    猜你喜欢
    • 2016-07-07
    • 1970-01-01
    • 1970-01-01
    • 2017-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-27
    • 1970-01-01
    相关资源
    最近更新 更多