TCL/Expect read from file (executing custom config in bulk)

At this point in time I need a nifty little tool to configure some ports on network devices. But the challenge is that the ports differ from device to device.

In order to do this I have to create a script to harvest data out of the network. Output files will be parsed through combination of bash/grep/awk.

The main thing I could not get my head around was how to read a file and hand data over to a spawned ssh session.

As a proof of concept I created a file with commands to execute on another node. And also a tiny tcl script to open a ssh session, logon, read the commands file, close the ssh session.

Contents of my commands.txt file is below, nothing fancy just to get the proof of concept.

du -h

Open a file to read , read into $file_data, close the file.

set fp [open "commands.txt" r]
set file_data [ read $fp ]
close $fp

Split the $file_data into usable chunks.

set dataln [ split $file_data "\n"]

Walkthrough the $dataln and give the data to the ssh session.

# loop through $dataln and store data in $line
foreach line $dataln {
  # just an obvisous expectation.
  expect ">" {
   # send the $line to ssh  session..
   send "$line\r"

Complete test.tcl (awesome name right 😉 )


set nethost [lindex $argv 0]
set netuser [lindex $argv 1]
set netpass [lindex $argv 2]

# -- file open magic here    
set fp [open "commands.txt" r]
set file_data [ read $fp ]
close $fp

# -- file_data read here , split to dataln
set dataln [ split $file_data"\n"]

spawn ssh "$netuser@$nethost"

expect "assword"{
   send "$netpass\r"

# -- walk through $dataln
foreach line $dataln{
   expect ">"{
   send "$line\r"

expect ">"{
   send "exit\r"

# in case exit fails...

This is the final result;

$ ./test.tcl  DS 1user SecRet
spawn ssh 1user@DS
1user@ds's password:  

BusyBox xxxxxxxxxxx
Enter 'help' for a list of built-in commands.

DiskStation> du -h
8.0K    ./.ssh
--//output omited for brevity//--
408.0K  ./script-test
496.0K  .
DiskStation> uname
DiskStation> exit
Connection to ds closed.

As you can imagine a little work still has to be done. Like creating a several files with configuration. While executing the bash/tcl wrapper handing over the config file as an argument. But that shouldn’t be to hard. Maybe something thing like this; (of course some sanity check have to be build in)

ls *config.txt |
while read file 
   echo "./wrapper.tcl ${file%_*} user pass $file"
This entry was posted in CCNP and tagged , . Bookmark the permalink.