9

I'm trying to run this script but having different errors when modified. Here is the code and the output. Please help.

Updates at the end of the post with debug info

    #!/bin/bash
    (( $# != 1 )) && { echo >&2 "Usage: $0 \"[COMMAND]\""; exit 1; }
    servers_addresses=(10.10.10.10 )
    for server_address in ${servers_addresses[@]}; do
    expect <<EOF
    spawn ssh -t root@$server_address "$*"
    expect -timeout 2 "Are you sure you want to continue connecting (yes/no)?" { send "yes\n" }
    expect "s password:" { send "Correct_Password\n" }
    expect "s password:" { send "Wrong_Password_22222\n" }
    expect "s password:" { send "Wrong_Password_33333\n" }
    expect eof
    EOF
    done

And the output is like:

    goldberg188@Test-Server ~$ ./test.sh "sudo cat /etc/hosts"
    spawn ssh -t [email protected] sudo cat /etc/hosts
    [email protected]'s password:
    # Do not remove the following line, or various programs
    # that require network functionality will fail.
    10.10.10.10             TEST-004 localhost.localdomain localhost
    ::1             localhost6.localdomain6 localhost6
    Connection to 10.10.10.10 closed.
    expect: spawn id exp4 not open
        while executing
    "expect "s password:" { send "Wrong_Password_33333\n" }"

If I modify like this, then the output would be bit different

    expect "s password:" { send "Wrong_Password_11111\n" }
    expect "s password:" { send "Correct_Password\n" }
    expect "s password:" { send "Wrong_Password_33333\n" }

    goldberg188@Test-Server ~$ ./test.sh "sudo cat /etc/hosts"
    spawn ssh -t [email protected] sudo cat /etc/hosts
    [email protected]'s password:
    # Do not remove the following line, or various programs
    # that require network functionality will fail.
    10.10.10.10             TEST-004 localhost.localdomain localhost
    ::1             localhost6.localdomain6 localhost6
    Connection to 10.10.10.10 closed.
    expect: spawn id exp4 not open
        while executing
    "expect eof"

And if the correct password in on the third line then no errors at all. Works fine on this one.

    expect "s password:" { send "Wrong_Password_11111\n" }
    expect "s password:" { send "Wrong_Password_22222\n" }
    expect "s password:" { send "Correct_Password\n" }


    goldberg188@Test-Server ~$ ./test.sh "sudo cat /etc/hosts"
    spawn ssh -t [email protected] sudo cat /etc/hosts
    [email protected]'s password:
    # Do not remove the following line, or various programs
    # that require network functionality will fail.
    10.10.10.10             TEST-004 localhost.localdomain localhost
    ::1             localhost6.localdomain6 localhost6
    Connection to 10.10.10.10 closed.

Ignore the Edits: I know how to run 2 commands at once.

Update: Debug info - Modified to

    exp_internal 1
    expect "s password:" { send "Wrong_Password_11111\n" }
    expect "s password:" { send "Correct_Password\n" }
    expect "s password:" { send "Wrong_Password_33333\n" }

Output:

    goldberg188@Test-Server ~$ ./test.sh "sudo cat /etc/host"
    spawn ssh -t [email protected] sudo cat /etc/host
    [email protected]'s password:
    expect: does "[email protected]'s password: " (spawn_id exp4) match glob pattern "s password:"? yes
    expect: set expect_out(0,string) "s password:"
    expect: set expect_out(spawn_id) "exp4"
    expect: set expect_out(buffer) "[email protected]'s password:"
    send: sending "Wrong_Password_11111\n" to { exp4 }

    expect: does " " (spawn_id exp4) match glob pattern "s password:"? no


    expect: does " \r\n" (spawn_id exp4) match glob pattern "s password:"? no
    Permission denied, please try again.
    [email protected]'s password:
    expect: does " \r\nPermission denied, please try again.\r\r\[email protected]'s password: " (spawn_id exp4) match glob pattern "s password:"? yes
    expect: set expect_out(0,string) "s password:"
    expect: set expect_out(spawn_id) "exp4"
    expect: set expect_out(buffer) " \r\nPermission denied, please try again.\r\r\[email protected]'s password:"
    send: sending "Correct_Password\n" to { exp4 }

    expect: does " " (spawn_id exp4) match glob pattern "s password:"? no


    expect: does " \r\n" (spawn_id exp4) match glob pattern "s password:"? no
    cat: /etc/host: No such file or directory
    Connection to 10.10.10.10 closed.

    expect: does " \r\ncat: /etc/host: No such file or directory\r\r\nConnection to 10.10.10.10 closed.\r\r\n" (spawn_id exp4) match glob pattern "s password:"? no
    expect: read eof
    expect: set expect_out(spawn_id) "exp4"
    expect: set expect_out(buffer) " \r\ncat: /etc/host: No such file or directory\r\r\nConnection to 10.10.10.10 closed.\r\r\n"
    expect: spawn id exp4 not open
        while executing
    "expect eof"
3
  • Try running with expect -d to get extra debugging output Nov 5, 2014 at 11:15
  • I've added the debug output at the end of the post. Please check now. Thanks Nov 5, 2014 at 11:45
  • show debug output where you send the wrong password first Nov 5, 2014 at 11:50

2 Answers 2

7

Assuming you're not sending a wrong password on purpose, use exp_continue as a looping construct:

expect <<EOF
set passwds {foo bar baz}
set i 0
spawn ssh -t root@$server_address "$*"
expect {
    "continue connecting (yes/no)?" { send "yes\r"; exp_continue }
    " password: " { send "[lindex $passwds $i]\r"; incr i; exp_continue }
    eof
}
EOF
5
  • Bro, I'm gonna use that script on our 100's Linux servers. 3 passwords are common. Either the first password works or the second one does or so on. So once I initiate a task, I don't want to sit around a computer to type passwords or to type yes if needed. so can you tell me how to try first password or second one or the third one using your script? I want the passwords to be saved in that scripts. IP's are gonna be through a file and I know to do that. Nov 5, 2014 at 14:56
  • It might be a wrong password, but it will work for some other servers. We have strict rule of password policy and based on the env, the passwords change that is why i might have 3 passwords or more in my script. Nov 5, 2014 at 14:58
  • I started to work on this after I had the ShellShock issue as I was forced to login to 100's of servers to update bash manually.. Nov 5, 2014 at 14:58
  • 5
    This may be relevant: xkcd.com/1319 Nov 5, 2014 at 15:01
  • @glennjackman A good answer. I tried this method to solve a similar problem with Telnet. But it does not always work as expected, so I try to use spawn telnet -l user_name to login. But there is still a problem. Could you please give me a hand?
    – John
    Jun 16, 2022 at 12:45
1

CREDITS: glenn jackman

Sorry Glenn your code need few changes which I'm adding here and got it working.

Here is the fixed code for anyone else who may need it. You can put the IP's in a text file and then cat inside the servers_addresses. like servers_addresses=('cat ip_list.txt')

In the IP List add IP's like this 10.10.10.1 10.10.10.2 10.10.10.3

also more examples if needed. Run a command:

    ./test.sh "sudo cat /etc/hosts"

Run Multiple commands

    ./test.sh "sudo cat /etc/hosts & /etc/init.d/network status"

Search and replace

    ./test.sh "sed -i -e 's/SEARCH_STRING/REPLACE_STRING/g' /tmp/FileNAME.txt"

The full code:

    #!/bin/bash
    (( $# != 1 )) && { echo >&2 "Usage: $0 \"[COMMAND]\""; exit 1; }
    servers_addresses=( 10.10.10.10 192.168.10.1 )
    for server_address in ${servers_addresses[@]}; do
        expect <<EOF
    set passwds { password1 password2 password3 }
    set i 0
    spawn ssh -t root@$server_address "$*"
    expect {
        "Are you sure you want to continue connecting (yes/no)?" { send "yes\r"; exp_continue }
        "s password:" { send "[lindex \$passwds \$i]\r"; incr i; exp_continue }
        eof
    }
    EOF
    done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .