Sync files with rsync(1)

tags: tutorials

Connecting local machines

In order to connect two machines on the same network, they both need to know each other’s network IP address. To get your network IP address execute the following command on each of the local machines you want to connect:

$ ifconfig

In your running network interface’s section, ifconfig will output a line that looks like this:

inet 192.168.x.y

This is your network IP address which the other machine needs to know. Suppose you want to connect two local machines at home; we’ll call the first one host1 and the other host2. the ip address for host1 is 192.168.1.7 and for host2 it’s 192.168.1.8. add the following line on host1’s /etc/hosts so that it knows who host2 is. do the same for host2.

192.168.1.8 host2

After completing this step ping each other using both the IP and the hostname to make sure everything works:

$ ping 192.168.1.8 

ping 192.168.1.8 (192.168.1.8): 56 data bytes
64 bytes from 192.168.1.8: icmp_seq=0 ttl=64 time=36.931 ms
...

$ ping host2

ping host2 (192.168.1.8): 56 data bytes
64 bytes from 192.168.1.8: icmp_seq=0 ttl=64 time=74.056 ms
...

If you don’t already have an ssh key pair, generate one:

$ ssh-keygen

Copy the ssh public key over to the other machine:

$ eval $(ssh-agent -s)
$ ssh-add
$ ssh-copy-id user@host2

Repeat the same process for host2. to verify that the key was indeed copied over, look at ~/.ssh/authorized_keys.

Using rsync

You can think of rsync as cp with superpowers; in fact, you could even alias cp to rsync.

To just copy a file on your machine you can do exactly the same thing you would do with cp:

$ rsync foo bar/

Suppose we want to send that file to host2 (read the previous section):

$ rsync foo host2:

By default, rsync assumes that the target user has the same name as yours. In case it’s different, you need to specify it:

$ rsync foo user@host2:

The file will be copied in the other machine’s home directory, if no other directory is specified. To send it to a specific path:

$ rsync foo user@host2:foo/

rsync has a lot of options, but some of the most common ones, and the ones I use most of the time are the following:

-r
Copy directories recursively.
-u
Update only the files that have changed (incremental copy).
-v
Increase verbosity.
-a
Preserve permissions and metadata. does not preserve hard links.
-p
In case something goes wrong and the sync breaks, continue the sync from where it stopped.
--delete-after
Delete the old files after the transfer.

Note: when you want to transfer a directory, you must add a / after its name (e.g foo/), otherwise rsync will skip it.

Sample usage

Suppose I want to update a website that is hosted on a remote server. I can make changes locally and just sync it with the server whenever I want using rsync. Let’s say the remote directory is located at /var/www/website:

$ rsync -purv --delete-after website/ user@server:/var/www/website

You can automate this process using a simple shell script. In this case though, you have to pass the absolute paths of the directories so that you can run the script from everywhere:

#!/bin/sh

src="/foo/bar/website/"
dst="user@server:/var/www/website"
rsync -purv --delete-after ${src} ${dst}