7

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 root@10.10.10.10 sudo cat /etc/hosts
    root@10.10.10.10'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 root@10.10.10.10 sudo cat /etc/hosts
    root@10.10.10.10'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 root@10.10.10.10 sudo cat /etc/hosts
    root@10.10.10.10'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 root@10.10.10.10 sudo cat /etc/host
    root@10.10.10.10's password:
    expect: does "root@10.10.10.10'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) "root@10.10.10.10'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.
    root@10.10.10.10's password:
    expect: does " \r\nPermission denied, please try again.\r\r\nroot@10.10.10.10'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\nroot@10.10.10.10'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"
0xC0000022L
  • 1,456
  • 2
  • 20
  • 41
GoldFlake129
  • 73
  • 1
  • 1
  • 5

2 Answers2

6

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
glenn jackman
  • 4,320
  • 16
  • 19
  • 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. – GoldFlake129 Nov 05 '14 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. – GoldFlake129 Nov 05 '14 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.. – GoldFlake129 Nov 05 '14 at 14:58
  • 4
    This may be relevant: https://www.xkcd.com/1319/ – glenn jackman Nov 05 '14 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](https://stackoverflow.com/q/72643674/13611002). Could you please give me a hand? – John Jun 16 '22 at 12:45
0

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
0xC0000022L
  • 1,456
  • 2
  • 20
  • 41
GoldFlake129
  • 73
  • 1
  • 1
  • 5