Below is a simple example of how to use expect for that.
First create some directories under the directory where you will be testing the script
you will need to create
./config - to hold a file containing the list of remote hosts
./data - the file that you are going to upload goes there
./logs - access logs will be written there
Now create a list of hosts in ./config directory (I called mine target_list) Put actual remote hostnames here
echo host1.mydomain.net:/tmp > ./config/target_list
echo host2.mydomain.net:/var/tmp >> ./config/target_list
The script will also parse target directory for each host - directory comes after the host name delimited with :. (Note, that I am not using these directories in this example)
Create your package file in ./data
I populated my package with the commands below
echo hello > test.log
cat test.log
And now the script itself (run it as ./test package_file target_list )
You will be prompted to enter your username and password for your remote hosts access. You need to enter this information only once. Ignore all other prompts.
Your package file will be delivered to /tmp directory on your remote hosts
#!/usr/bin/expect -f set packagename [lrange $argv 0 0] set targets_list_file [lrange $argv 1 1] set dir_config ./config set dir_data ./data set dir_log ./logs set dir_target /tmp set myname $argv0 set timeout 20 log_file -noappend -a ${dir_log}/${packagename}_access_log set prompt "(#|%|\\\]|\\\$|>).*" ## ## If script started without parameters, prompt for correct usage ## proc usage {myname} { send_error "\nIncorrect usage !\n" send_error "\nShould run as following :\n" send_error "\n $myname \[Package\] \[hosts\]\n" send_error "\n Exiting ...\n" send_error "\n" } ## ## Get username ## proc getuser {} { set timeout -1 send_user "Login : " expect_user -re "(.*)\n" send_user "\n" set timteout 10 return $expect_out(1,string) } ## ## Get password ## proc getpassword {} { set timeout -1 stty -echo send_user "Password : " expect_user -re "(.*)\n" send_user "\n" stty echo set timeout 20 return $expect_out(1,string) } ## ## If started with correct parameters, run script ## if { $argc == 2 } { puts "Connecting to target hosts and running scripts ..." set targets_list [open ${dir_config}/${targets_list_file}] } else { usage $myname ; exit 1 } ## ## Get user and password ## set user [ getuser ] expect * set password [ getpassword ] expect * ## ## Loop through the target hosts ## while { [gets ${targets_list} input] != -1 } { set host [lrange [split $input ":"] 0 0] set targetdir [lrange [split $input ":"] 1 1] ### ### copy package using scp ### spawn scp ${dir_data}/${packagename} $user@$host:${dir_target} match_max 100000 expect { -re ".*Are.*.*yes.*no.*" { send "yes\r" exp_continue } # #look for the password prompt # "?assword:" { send -- "$password\r" exec sleep 2 } default { continue } } expect { -re "$prompt" { send "hostname\r" } "?assword:" { send_user "\n\nIncorrect login or password !\n\n\r" ; exit 1 } default { send_user "\n\nLogin time out !\n\n\r" ; continue } } ### ### End copy package ### ### ### ssh into remote host ### spawn ssh $user@$host match_max 100000 expect { -re ".*Are.*.*yes.*no.*" { send "yes\r" exp_continue #look for the password prompt } "?assword:" { send -- "$password\r" exec sleep 2 } default { continue } } expect { -re "$prompt" { send "hostname\r" } "?assword:" { send_user "\n\nIncorrect login or password !\n\n\r" ; exit 1 } default { send_user "\n\nLogin time out !\n\n\r" ; continue } } ## ## Give full permissions to the copied file ## (\r needed in the end of each command) ## expect -re "$prompt" send "chmod 777 ${dir_target}/${packagename}\r" ## ## cd into target directory - ${dir_target} - set as /tmp in this script ## expect -re "$prompt" send "cd ${dir_target}\r" ## ## check if the package was delivered to the target directory ## expect -re "$prompt" send "ls -lrt ${dir_target}/${packagename}\r" ## ## run the package script ## expect -re "$prompt" send "${dir_target}/${packagename} \r" } ## ## End of loop through hosts ## ### ### exit, close target list file ### expect -re "$prompt" send "exit\r" expect eof close $targets_list puts "\n" |