Download your favorite Linux distribution at LQ ISO.
Go Back > Forums > Non-*NIX Forums > Programming
User Name
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.


  Search this Thread
Old 10-16-2012, 06:36 PM   #1
LQ Newbie
Registered: Jun 2009
Distribution: Debian, RHEL, FreeBSD
Posts: 17

Rep: Reputation: 0
Bash and Expect to Update a Large List of Servers

I am attempting to write a script that will run system updates on about 30 linux servers (mixed distributions). For now I am focusing on debian to keep things simple. The script is composed of three parts: A bash script that reads a file containing the list of servers and executes an expect script located on each server. I have a decent grasp of bash and am very new to expect with little no knowledge of how bash and expect behave together.

The list of servers is written in a hosts file: all_hosts

? List of servers to update
? Preceeding question mark is a commented line
? port separated by percent then hostname
? port%server
The main bash script reads this file and loops through. This part of the script works. I have been using this for some time now to move files between all my servers. Here is the main bash script: update_all

 1 #!/bin/bash
  3 # update_all
  5 # There are three variables accepted via commandline
  6 # $1 = first parameter (/source_path/source_filename)
  7 # $2 = second parameter (/target_directory/)
  8 # $3 = third paramter (file that contains list of hosts)
 11 PASS=$2
 13 if [ $# -ne 2 ]; then
 14         echo "usage: $0 [hostsfile] [password]"
 15         exit 1
 16 elif [ -f $HOSTFILE ]; then
 17    printf "Begining update process ...\n"
 18    while read line; do
 19         COMMENT=`expr index "$line" ?`
 20         if [ $COMMENT -lt 1 ]; then
 21                 SEPER=`expr index "$line" %`
 22                 SERVER=${line:SEPER}
 23                 let SEPER-=1
 24                 PORT=${line:0:SEPER}
 25                 echo "$SERVER: "
 26                 ssh -p $PORT $SERVER '/home/user/update $2'
 27         fi
 28         done < $HOSTFILE
 29 else
 30    printf "File \"$HOSTFILE\" not found\n"
 31    exit 0
 32 fi
 33 exit 0
You can see on line 26 in update_all, the update process is executed via SSH. So on each server there is an expect script called update which is an expect script that looks like:

  1 #!/usr/bin/expect
  3 set timeout 10
  5 set pass [lindex $argv 0]
  7 spawn sudo apt-get clean
  8 expect "*?assword*"
  9 send "$pass\r";
 10 interact
 12 spawn sudo apt-get update
 13 expect "*?assword*"
 14 send "$pass\r";
 15 interact
 17 spawn sudo apt-get -yq upgrade
 18 expect "*?assword*"
 19 send "$pass\r";
 20 interact
Now this expect script works when executed locally on each server. So the command looks like:

$ ./update "mypassword"
Back on my central server if I put it all together:

$ ./update_all all_hosts "mypassword"
Begining update process ...
spawn sudo apt-get clean
[sudo] password for user: interact: spawn id exp0 not open
    while executing
    (file "/home/user/update" line 15)
I have scoured google around this error but I believe the problem is a fundamental misunderstanding on my part. All the information I have found points to using different methods alltogether, for example: My questions are thus:
  1. Does my approach seem reasonable? As in, using bash and expect in this manner.
  2. Does this approach have any security risks?
  3. What does the above error mean and how can I mitigate it?


Last edited by Obscurious; 10-16-2012 at 06:42 PM.
Old 10-16-2012, 06:48 PM   #2
LQ Newbie
Registered: Jun 2009
Distribution: Debian, RHEL, FreeBSD
Posts: 17

Original Poster
Rep: Reputation: 0
I should also add that I have a uniform account on all my servers hooked up to LDAP, so my sudo password is the same on all hosts. I also have SSH keys setup so the SSH command requires no password.
Old 10-17-2012, 01:14 AM   #3
Registered: Mar 2006
Location: Ekaterinburg, Russia
Distribution: Debian, Ubuntu
Posts: 709

Rep: Reputation: 427Reputation: 427Reputation: 427Reputation: 427Reputation: 427

In this line
  ssh -p $PORT $SERVER '/home/user/update $2'
you use single quotes, so this will not work unless your sudo password looks exactly like '$2' (literally).

From man bash:
Enclosing characters in single quotes preserves the literal value of each character within
the quotes. A single quote may not occur between single quotes, even when preceded by a

Enclosing characters in double quotes preserves the literal value of all characters within
the quotes, with the exception of $, `, \, and, when history expansion is enabled, !. The
characters $ and ` retain their special meaning within double quotes. The backslash retains
its special meaning only when followed by one of the following characters: $, `, ", \, or
<newline>. A double quote may be quoted within double quotes by preceding it with a back‐
slash. If enabled, history expansion will be performed unless an ! appearing in double
quotes is escaped using a backslash. The backslash preceding the ! is not removed.
Try double quotes "..." instead.

Last edited by firstfire; 10-17-2012 at 01:16 AM.


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
ssh to servers with spawn,expect,send by script itamarm Linux - Newbie 4 01-14-2012 02:33 PM
how to use expect - send to execute list of commands inside a file auma78 Linux - General 1 02-02-2011 01:00 PM
Bash script to fgrep a large file. With list as source for searching. the_file Linux - Newbie 14 01-24-2011 04:42 PM
[SOLVED] /usr/bin/expect : Script to check server load using both expect and bash Soji Antony Programming 1 07-28-2010 12:27 AM
Good list / forum for expect programmer? Hewson Programming 2 05-04-2007 03:23 PM > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:15 AM.

Main Menu
Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration