Read file into String and do a loop in Expect Script
Asked Answered
V

3

8

What I am trying to do is to:

  1. Create a .exp file, which will read from the *.txt file from the same directory and parse all the content in the text file into a string variable in the expect script.
  2. Loop the string, which contains a series of host names, and excecute a series of command until the string is enumerated.

So what the script does, is read a series of hostname from a txt file in the same directory, and then read them into a string, and the .exp file will auto log into each of them and excecute a series of commands.

I have the following code written but it's not working:

#!/usr/bin/expect

set timeout 20
set user test
set password test

set fp [open ./*.txt r]
set scp [read -nonewline $fp]
close $fp

spawn ssh $user@$host

expect "password"
send "$password\r"

expect "host1"
send "$scp\r"

expect "host1"
send "exit\r"

Any help is greatly appreciated....

Valentino answered 15/7, 2013 at 19:35 Comment(3)
I'm a little bit confused. Do you have one file listing all the commands and another listing all the hosts? Or do you have a directory with one file per host (named by hostname with .txt extension?) that holds the command(s) to run on that host?Nonviolence
hello. I am trying to create a loop. first read the file host.txt, which contains all the servers that I want the exp script to run on. And then, while the eof of the host.txt, copy and paste the commands that are in commands.txt file into each host.Valentino
which also means the expect command in this script will expect a number of different hosts, such as $host1->, $host2-> etc....Valentino
N
20

The code should read the contents of the two files into lists of lines, then iterate over them. It ends up like this:

# Set up various other variables here ($user, $password)

# Get the list of hosts, one per line #####
set f [open "host.txt"]
set hosts [split [read $f] "\n"]
close $f

# Get the commands to run, one per line
set f [open "commands.txt"]
set commands [split [read $f] "\n"]
close $f

# Iterate over the hosts
foreach host $hosts {
    spawn ssh $user@host
    expect "password:"
    send "$password\r"

    # Iterate over the commands
    foreach cmd $commands {
        expect "% "
        send "$cmd\r"
    }

    # Tidy up
    expect "% "
    send "exit\r"
    expect eof
    close
}

You could refactor this a bit with a worker procedure or two, but that's the basic idea.

Nonviolence answered 17/7, 2013 at 10:35 Comment(0)
C
5

I'd refactor a bit:

#!/usr/bin/expect

set timeout 20
set user test
set password test

proc check_host {hostname} {
    global user passwordt

    spawn ssh $user@$hostname
    expect "password"
    send "$password\r"
    expect "% "                ;# adjust to suit the prompt accordingly
    send "some command\r"
    expect "% "                ;# adjust to suit the prompt accordingly
    send "exit\r"
    expect eof
}

set fp [open commands.txt r]
while {[gets $fp line] != -1} {
    check_host $line
}
close $fp
Chayachayote answered 15/7, 2013 at 19:50 Comment(0)
R
1

Using any of the two solutions here, I would also create a logfile that you can view at a later time. Makes it easy to troubleshoot any problems after the script is run, especially if you're configuring several hundred hosts.

Add:

log_file -a [log file name]

Before your loop.

Cheers,

K

Rosenda answered 24/4, 2015 at 16:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.