How can I make an expect script prompt for a password?

后端 未结 3 1747
半阙折子戏
半阙折子戏 2020-11-29 04:57

I have an expect script that connects to a few routers through ssh. All these routers have the same password (I know, it\'s wrong), and the script needs to know that passwo

相关标签:
3条回答
  • 2020-11-29 05:14

    Use expect's stty command like this:

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

    Note that it's important to call stty -echo before calling send_user -- I'm not sure exactly why: I think it's a timing issue.

    expect programmers should all read the book: Exploring Expect by Don Libes

    0 讨论(0)
  • 2020-11-29 05:28

    Alternatively you could let ssh collect the password via X11 using the SSH_ASKPASS environment variable.

    From the man page:

    > 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.)
    
    0 讨论(0)
  • 2020-11-29 05:32

    OK, merging the 2 answers above (or below or wherever they are now!):

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

    Note that I changed the $password variable to $pass to be consistent with the other answer.

    0 讨论(0)
提交回复
热议问题