-1

I have an expect script that I would like to use to check disk health on SuSE servers. The expect script will/would take the output of df -T|grep ext*|awk '{print $1}' to generate a list for ext2 or 3 type disk drives. I can then take that list and iterate thought it, executing e2fsck -n $partition and dumpe2fs -h $partition.

I have a start on the script, I have omitted the access part as that is straight forward.

The issue I have is this only works if the partition file(parts.txt), exists on the server that I spawn the expect script on. I had hoped that all the work could be done on the server that I login to.

send_user "\nthese are the ext partitions on this element\n"
exp_send "df -T|grep ext*\|awk \'\{ print \$1 \}\' > parts.txt\r
expect "#"
set f [open "parts.txt" r]
while { [ gets $f part ] != -1} {
    exp_send "dumpe2fs -h $part\r"
    expect "#"
    exp_send "e2fsck -n $part\r"
    expect "#"
}
close $f
exp_send "exit\r"
expect {
    -re "~ #" {
        exp_send "exit\r"
    }
    -re ":~>" {
        exp_send "exit\r"
    }
}
expect eof
Donal Fellows
  • 133,037
  • 18
  • 149
  • 215

1 Answers1

0

You either need to transfer the parts list to the local side (i.e., the system that actually runs expect) or you need to move the iteration to the remote side. If I had to choose between the two approaches, I'd probably use the first option; that would give me far more options for complex handling of unexpected conditions.

Getting the list locally

To move the part list locally, we adapt your script so that it runs the df … command and writes the output to where we can see it, and use a more complex expect command to process the output.

exp_send "df -T|grep ext*|awk '{ print \$1 }'\r"
set theParts {}
expect {
    -re {[^\s#]+} {
        lappend theParts $expect_out(0,string)
        exp_continue
    }
    "#" {
        # Just an empty script here
    }
}

This expect will look for two things at once, but with the first one if it finds a sequence of non-space non-hash characters, it appends that sequence (stored by default in that particular “field” of the expect_out array) to the list in the variable theParts and keeps waiting. (That's what the exp_continue does.)

Now that you have a list, you could write it out to a local parts.txt, but why would you bother? Might as well use foreach to walk over it directly:

foreach part $theParts {
    exp_send "dumpe2fs -h $part\r"
    expect "#"
    exp_send "e2fsck -n $part\r"
    expect "#"
}

Moving the looping remotely

The other approach is to put the looping on the other machine.

exp_send "df -T|grep ext*|awk '{ print \$1 }' >parts.txt\r"
expect "#"
exp_send "for part in `cat parts.txt`; do dumpe2fs -h \$part || break; e2fsck -n \$part || break; done\r"
expect "#"

This is quite a bit shorter, but in the form above not very robust. You can make robust shell scripts, but it takes quite a bit of work (and is much easier in my experience if you write the shell script itself to a file on the remote host and then run it from there).

For your understanding, the looping script I've done above is this (when split over multiple lines and without the backslashes for Tcl, which are only really needed before Tcl metacharacters — in this script, that's $ only):

for part in `cat parts.txt`; do
    dumpe2fs -h $part || break
    e2fsck -n $part || break
done
Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • Thank You @Donal Fellows I am getting closer with your help. I have implemented the last option, and moved the looping to the remote server. As it stand now, my loop moves only once, it appears to execute only on the first /dev/sdaX in the parts.txt file. – user3583566 Jul 07 '17 at 02:03