代码之家  ›  专栏  ›  技术社区  ›  MiniQuark

如何使Expect脚本提示输入密码?

  •  20
  • MiniQuark  · 技术社区  · 16 年前

    我有一个expect脚本,通过ssh连接到一些路由器。所有这些路由器都有相同的密码(我知道,这是错误的),脚本需要知道该密码才能连接到路由器。目前,密码在命令行上作为参数传递给我的脚本,但这意味着在我的.bash_历史文件以及正在运行的进程中都有该密码的痕迹。因此,如果可能的话,我希望提示用户输入密码。

    您知道是否可以用expect提示用户输入密码吗?

    谢谢您。

    编辑 :如果我连接的是服务器而不是路由器,我可能会使用ssh密钥而不是密码。但是我使用的路由器只支持密码。

    3 回复  |  直到 7 年前
        1
  •  35
  •   glenn jackman    16 年前

    使用预期 stty 命令如下:

    # grab the password
    stty -echo
    send_user -- "Password for $user@$host: "
    expect_user -re "(.*)\n"
    send_user "\n"
    stty echo
    set pass $expect_out(1,string)
    
    #... later
    send -- "$pass\r"
    

    注意,打电话很重要 stty -echo 之前 打电话 send_user --我不清楚原因:我认为这是个时间问题。

    希望程序员都能阅读 这个 书:唐·利伯斯的《探索期待》

        2
  •  6
  •   dr-jan    7 年前

    好的,合并上面的两个答案(或下面的答案,或它们现在所在的位置!):

    #!/usr/bin/expect
    log_user 0
    set timeout 10
    set userid  "XXXXX"
    set pass    "XXXXXX"
    
    ### Get two arguments - (1) Host (2) Command to be executed
    set host    [lindex $argv 0] 
    set command [lindex $argv 1]
    
    # grab the password
    stty -echo
    send_user -- "Password for $userid@$host: "
    expect_user -re "(.*)\n"
    send_user "\n"
    stty echo
    set pass $expect_out(1,string)
    
    spawn /usr/bin/ssh -l $userid $host
    match_max [expr 32 * 1024]
    
    expect {
        -re "RSA key fingerprint" {send "yes\r"}
        timeout {puts "Host is known"}
    }
    
    expect {
         -re "username: " {send "$userid\r"} 
         -re "(P|p)assword: " {send "$pass\r"}
         -re "Warning:" {send "$pass\r"}
         -re "Connection refused" {puts "Host error -> $expect_out(buffer)";exit}
         -re "Connection closed"  {puts "Host error -> $expect_out(buffer)";exit}
         -re "no address.*" {puts "Host error -> $expect_out(buffer)";exit}
    
         timeout {puts "Timeout error. Is host down or unreachable?? ssh_expect";exit}
    }
    
    expect {
       -re "\[#>]$" {send "term len 0\r"}
       timeout {puts "Error reading prompt -> $expect_out(buffer)";exit}
    }
    
    
    expect {
       -re "\[#>]$" {send "$command\r"}
    
       timeout {puts "Error reading prompt -> $expect_out(buffer)";exit}
    }
    
    expect -re "\[#>]$"
    set output $expect_out(buffer)
    send "exit\r"
    puts "$output\r\n"
    

    请注意,我将$password变量更改为$pass,以便与另一个答案保持一致。

        3
  •  0
  •   qneill Adam Burry    14 年前

    或者,您可以让ssh通过x11使用ssh_askpass环境变量收集密码。

    从手册页:

    > SSH_ASKPASS
    >     If ssh needs a passphrase, it will read the passphrase from the
    >     current terminal if it was run from a terminal.  If ssh does not
    >     have a terminal associated with it but DISPLAY and SSH_ASKPASS
    >     are set, it will execute the program specified by SSH_ASKPASS
    >     and open an X11 window to read the passphrase.  This is particularly
    >     useful when calling ssh from a .xsession or related script.
    >     (Note that on some machines it may be necessary to redirect the
    >     input from /dev/null to make this work.)