96

I have some n number of files in a directory on my unix system. Is there a way to write a shellscript that will transfer all those files via scp to a specified remote system. I'll specify the password within the script, so that I don't have to enter it for each file.

Pradeep Pati
  • 5,779
  • 3
  • 29
  • 43
  • 2
    Can you please tell me if using a password in shell script with rsync worked or if you tried that? thanks. –  Aug 07 '10 at 21:22

14 Answers14

104

Instead of hardcoding password in a shell script, use SSH keys, its easier and secure.

$ scp -i ~/.ssh/id_rsa *.derp devops@myserver.org:/path/to/target/directory/

assuming your private key is at ~/.ssh/id_rsa and the files you want to send can be filtered with *.derp

To generate a public / private key pair :

$ ssh-keygen -t rsa

The above will generate 2 files, ~/.ssh/id_rsa (private key) and ~/.ssh/id_rsa.pub (public key)

To setup the SSH keys for usage (one time task) : Copy the contents of ~/.ssh/id_rsa.pub and paste in a new line of ~devops/.ssh/authorized_keys in myserver.org server. If ~devops/.ssh/authorized_keys doesn't exist, feel free to create it.

A lucid how-to guide is available here.

Pradeep Pati
  • 5,779
  • 3
  • 29
  • 43
  • 3
    Even after following these instructions, I am still prompted for a password...are there other criterion that I am missing? – scottysseus Jul 07 '15 at 19:09
  • @ScottScooterWeidenkopf there could be a few things that could be wrong, like the .ssh dir or the authorized_keys files may not have right permissions (700). – Pradeep Pati Jul 08 '15 at 12:21
  • 2
    @PradeepPati I figured out my problem. You're right, the problem was the permissions. In the link you provided, the author mentioned some permission changes. I made those changes, and now everything works. – scottysseus Jul 08 '15 at 13:07
  • 1
    Just to help avoid confusion with copy-paste usage of this solution, currently this answer seems to transfer FROM remote TO local -- which is opposite to what the OP is looking to do. – Ciabaros Sep 27 '20 at 18:35
  • @Ciabaros good catch! I updated the answer. thanks! – Pradeep Pati Sep 29 '20 at 06:05
42
#!/usr/bin/expect -f

# connect via scp
spawn scp "user@example.com:/home/santhosh/file.dmp" /u01/dumps/file.dmp
#######################
expect {
  -re ".*es.*o.*" {
    exp_send "yes\r"
    exp_continue
  }
  -re ".*sword.*" {
    exp_send "PASSWORD\r"
  }
}
interact

http://blogs.oracle.com/SanthoshK/entry/automate_linux_scp_command

JohnA
  • 1,875
  • 8
  • 28
  • 34
  • Note for windows users: The `expect` packaged in MSYS2 will match against the whole output, so the 1st rule will always be matched. If you exchange the order of both rules, you get the desired behaviour. – fzbd Jan 20 '18 at 13:50
24

why don't you try this?

password="your password"
username="username"
Ip="<IP>"
sshpass -p "$password" scp /<PATH>/final.txt $username@$Ip:/root/<PATH>
Veerendra K
  • 2,145
  • 7
  • 32
  • 61
18

you could also use rsync. It seems to work better for multiple files than scp IMHO.

rsync -avzh /path/to/dir/ user@remote:/path/to/remote/dir/

Update

You can use rsync via ssh by adding the '-e' switch:

rsync -avzh -e ssh /path/do/dir/ user@remote:/path/to/remote/dir/
bsisco
  • 799
  • 6
  • 11
  • 4
    The nice thing about scp ist that it uses a secure channel. rsync does not. –  Aug 28 '09 at 11:52
  • 4
    You can force rsync to use ssh: 'rsync -avz -e ssh remoteuser@remotehost:/remote/dir /this/dir/' –  Aug 28 '09 at 11:57
  • @flokra. Thanks, I was right in the middle of adding that update and got distracted. – bsisco Aug 28 '09 at 12:03
  • 10
    This will still invoke an interactive password prompt. I believe the OP wanted a fully automated solution – Tom Auger Jul 14 '11 at 22:19
  • @Dimitri scp -r copies files recursively. It has nothing to do with storing a password within the script and passing it to the scp call via a bash script! I don't really understand your comment. – Tom Auger Aug 17 '11 at 16:25
10
#!/usr/bin/expect -f
spawn scp -r BASE.zip abhishek@192.168.1.115:/tmp
expect "password:"
send "wifinetworks\r"
expect "*\r"
expect "\r"
sth
  • 222,467
  • 53
  • 283
  • 367
Abhinav Gupta
  • 101
  • 1
  • 2
  • Can expect be used for rsync? I am trying to do something and my RSA key method is not working. It keeps asking me the password for the remote machine. –  Aug 07 '10 at 21:22
5

If you are ok with entering your password once for every run of the script, you can do so easily using an SSH master connection.

#!/usr/bin/env bash

USER_AT_HOST="user@host"  # use "$1@$2" here if you like
SSHSOCKET=~/".ssh/$USER_AT_HOST"

# This is the only time you have to enter the password:
# Open master connection:
ssh -M -f -N -o ControlPath="$SSHSOCKET" "$USER_AT_HOST"

# These do not prompt for your password:
scp -o ControlPath="$SSHSOCKET" file1.xy "$USER_AT_HOST":remotefile1.xy
scp -o ControlPath="$SSHSOCKET" file2.xy "$USER_AT_HOST":remotefile2.xy

# You can also use the flag for normal ssh:
ssh -o ControlPath="$SSHSOCKET" "$USER_AT_HOST" "echo hello"
ssh -o ControlPath="$SSHSOCKET" "$USER_AT_HOST" "echo world"

# Close master connection:
ssh -S "$SSHSOCKET" -O exit "$USER_AT_HOST"
Felix Rabe
  • 4,206
  • 4
  • 25
  • 34
5

rsync is a program that behaves in much the same way that rcp does, but has many more options and uses the rsync remote-update protocol to greatly speed up file transfers when the destination file is being updated.

The rsync remote-update protocol allows rsync to transfer just the differences between two sets of files across the network connection, using an efficient checksum-search algorithm described in the technical report that accompanies this package.


Copying folder from one location to another

   #!/usr/bin/expect -f   
   spawn rsync -a -e ssh username@192.168.1.123:/cool/cool1/* /tmp/cool/   
   expect "password:"   
   send "cool\r"   
   expect "*\r"   
   expect "\r"  
Jeremy
  • 1
  • 85
  • 340
  • 366
4

What about wildcards or multiple files?

scp file1 file2 more-files* user@remote:/some/dir/
2

You can do it with ssh public/private keys only. Or use putty in which you can set the password. scp doesn't support giving password in command line.

You can find the instructions for public/private keys here: http://www.softpanorama.org/Net/Application_layer/SSH/scp.shtml

Vereb
  • 14,388
  • 2
  • 28
  • 30
2

There are 2 quick ways of achieving this:

  1. Using scp

    #!/usr/bin/env bash
    
    password="YOURPASSWORD"
    username="YOURUSERNAME"
    dir_origin="YOURSOURCEDIRECTORY"
    dir_destination="REMOTEDESTINATION"
    Ip="SERVERIP"
    
    echo "Uploading files to remote server...."
    sshpass -p "$password" scp -rC $dir_origin $username@$Ip:$dir_destination
    echo "File upload to remote server completed! ;)"
    
    
  2. Using rsync

    #!/usr/bin/env bash
    
    password="YOURPASSWORD"
    username="YOURUSERNAME"
    dir_origin="YOURSOURCEDIRECTORY"
    dir_destination="REMOTEDESTINATION"
    Ip="SERVERIP"
    
    echo "Uploading files to remote server...."
    sshpass -p "$password" rsync -avzh $dir_origin $username@$Ip:$dir_destination
    echo "File upload to remote server completed! ;)"
    

**NOTE :**You need to install sshpass (eg by running apt install sshpass for deb like os eg Ubuntu) that will enable you to auto upload files without password prompts

1

This will work:

#!/usr/bin/expect -f

spawn scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no file1 file2 file3 user@host:/path/
expect "password:"
send "xyz123\r"
expect "*\r"
expect "\r"
interact
1

here's bash code for SCP with a .pem key file. Just save it to a script.sh file then run with 'sh script.sh'

Enjoy

#!/bin/bash
#Error function
function die(){
echo "$1"
exit 1
}

Host=ec2-53-298-45-63.us-west-1.compute.amazonaws.com
User=ubuntu
#Directory at sent destination
SendDirectory=scp
#File to send at host
FileName=filetosend.txt
#Key file
Key=MyKeyFile.pem

echo "Aperture in Process...";

#The code that will send your file scp
scp -i $Key $FileName $User@$Host:$SendDirectory || \
die "@@@@@@@Houston we have problem"

echo "########Aperture Complete#########";
0

Try lftp

lftp -u $user,$pass sftp://$host << --EOF--

cd $directory

put $srcfile

quit

--EOF--
azazil
  • 31
  • 1
-1

The command scp can be used like a traditional UNIX cp. SO if you do :

scp -r myDirectory/ mylogin@host:TargetDirectory

will work

Dimitri
  • 8,122
  • 19
  • 71
  • 128