Automate SCP in Network – Script Guide

expectscriptingssh

I have a network full of Linux machines. In this network, I have a user as user1 with the password as password in all the machines.

I have the following script to put files in the home directory of user1 in all the machines of the network.

#!/usr/bin/expect -f

# connect via scp
spawn cat /home/user1/Desktop/IPlistfile.txt | while read line do
spawn scp /home/user1/Desktop/filetobesent.txt user1@${line}:/home/user1/Desktop
#######################
expect {
-re ".*es.*o.*" {
exp_send "yes\r"
exp_continue
}
-re ".*sword.*" {
exp_send "password\r"
}
}
interact
done

The problem is I am getting an error message as "can't read line. No such variable". However, if I use a IP address directly instead of the line variable, I am able to transfer the file.

Edit: The IPlistfile.txt contains the list of IP addresses in my network. Each line contains a single IP address.

Best Answer

I can think of a couple of ways to do this but I highly recommend setting up passwordless ssh access, you'll thank me later.

1. Set up passwordless access to your machines.

This is by far the best method since you are bound to want to connect to the machines again and this will make your life much easier. It is also way, way safer than the other options even if you choose to use an empty passphrase since you won't be throwing passwords around unencrypted.

First, create a public ssh key on your machine:

ssh-keygen -t rsa

You will be asked for a passphrase which you will be asked to enter the first time you run any ssh command after each login. This means that for multiple ssh or scp commands, you will only have to enter it once. Nevertheless, you can leave it empty to have completely passwordless access.

Once you have generated your public key, copy it over (as user1) to each computer in your network :

while read ip; do 
 ssh-copy-id -i ~/.ssh/id_rsa.pub user1@$ip 
done < IPlistfile.txt

You will have to manually enter the password for each IP (unless you use one of the solutions below for this step as well) but once you've done that, you will be able to copy files to any of these machines with a simple:

while read ip; do
  scp /home/user1/Desktop/filetobesent.txt user1@$ip:~/Desktop
done < IPlistfile.txt

If you have sshpass installed, you can automate this so you don't need to type your password for each machine:

SSHPASS='password'
while read ip; do
  sshpass -e  scp /home/user1/Desktop/filetobesent.txt user1@$ip:~/Desktop
done < IPlistfile.txt

2. Install sshpass

This is a nifty little program that allows you to pass an ssh password as a command line parameter. This is, obviously, not a very secure solution and I highly recommend you read the "Security Consideretions" section of man sshpass.

Anyway, it is probably available in your distribution's repositories, on Debian-based systems it can be installed with

sudo apt-get install sshpass

I can't check since I don't have a RedHat based machine but as far as I can tell from searching here, it should be installable on Fedora with

sudo yum install sshpass

Once you have it installed, you can simply run

SSHPASS='password'
while read ip; do
  sshpass -e scp /home/user1/Desktop/filetobesent.txt user1@$ip:~/Desktop
done < IPlistfile.txt

The -e option tells sshpass to get the password from the SSHPASS variable. This is a bit more secure than giving it as a parameter with the -p option.

IMPORTANT:

This will fail silently if the server you are connecting to is unknown, if its public key is not stored in your machine. If this does not seem to be working, just connect once (ssh or scp) to the remote machine and accept its public key.

3. Use pscp instead

pscp is an alternative to scp that accepts the password as a commandline parameter. On Debian-based systems, this can be installed with

sudo apt-get install putty-tools

As I said before, I can't check but it should be installable on Fedora with

sudo yum install putty

You can then copy your files with

while read ip; do
  pscp -pw password /home/user1/Desktop/filetobesent.txt user1@$ip:~/Desktop
done < IPlistfile.txt
Related Question