I found myself writing a Makefile for several tasks to manage this website, which uses Hugo. Of course, I use rsync, a truly tremendous tool, to deploy the files to my remote server.
This will be a short article about it.
Definition
rsync stands for remote sync and is used to transfer files from a source location to a destination location. The destination can be either local or remote, and it uses ssh as its remote shell by default, although it can use others such as rsh.
Its algorithm ensures that only the files that have changed since the last sync will be copied over, which it determines by looking at a file’s modification time.
Examples
Here are the flags used in these examples:
-a - Archive mode; equals
-rlptgoD(no-H,-A,-X).-z - Compress file data during the transfer.
-P - Same as
--partial --progress.-v - Increase verbosity.
–delete - Delete files from the destination directory if they are removed from the source.
Let’s create our workspace:
$ mkdir -p tmp/{foo,bar}
$ cd tmp
$ touch bar/file_{0..4}
This creates a directory structure like the following:
$ tree tmp
tmp
├── bar
│ ├── file_0
│ ├── file_1
│ ├── file_2
│ ├── file_3
│ ├── file_4
└── foo
2 directories, 5 files
Copying
Now, let’s copy all of the files from bar to foo:
~/tmp:$ rsync -az bar/ foo
~:$ tree ../tmp
../tmp
├── bar
│ ├── file_0
│ ├── file_1
│ ├── file_2
│ ├── file_3
│ ├── file_4
└── foo
├── file_0
├── file_1
├── file_2
├── file_3
├── file_4
2 directories, 10 files
The forward slash (/) after the source location tells rsync to copy only the contents of bar. If the slash is omitted, it will copy the directory, too.
~/tmp:$ tree ../tmp
../tmp
├── bar
│ ├── file_0
│ ├── file_1
│ ├── file_2
│ ├── file_3
│ ├── file_4
└── foo
└── bar
├── file_0
├── file_1
├── file_2
├── file_3
├── file_4
3 directories, 10 files
Verbosity
There’s verbose mode:
~/tmp:$ rsync -avz bar/ foo
sending incremental file list
./
file_0
file_1
file_2
file_3
file_4
sent 314 bytes received 114 bytes 856.00 bytes/sec
total size is 0 speedup is 0.00
And running again without having modified any of the files won’t transfer anything:
~/tmp:$ rsync -avz bar/ foo
sending incremental file list
sent 127 bytes received 12 bytes 278.00 bytes/sec
total size is 0 speedup is 0.00
Now, let’s modify a file:
~/tmp:$ touch bar/file_2
~/tmp:$ rsync -avz bar/ foo
sending incremental file list
file_2
sent 175 bytes received 35 bytes 420.00 bytes/sec
total size is 0 speedup is 0.00
Weeeeeeeeeeeeeeeeeeeeeeeeeeeee
Syncing
Adding the --delete switch will keep the directories truly in sync:
~/tmp:$ rm bar/file_3
~/tmp:$ rsync -avz --delete bar/ foo
sending incremental file list
deleting file_3
sent 125 bytes received 22 bytes 294.00 bytes/sec
total size is 0 speedup is 0.00
~/tmp:$ tree ../tmp
../tmp
├── bar
│ ├── file_0
│ ├── file_1
│ ├── file_2
│ └── file_4
└── foo
├── file_0
├── file_1
├── file_2
└── file_4
2 directories, 8 files
Remote Transfer
rsync -azP --delete bar/ kilgoretrout@vonnegut:/var/www/foo/
Makefile
Here be a simple Makefile:
CC = hugo
FLAGS = -D
DEST = /path/to/document_root/
SYSTEM = kilgoretrout@vonnegut
TARGET = public
.PHONY: build clean deploy serve
build:
$(CC)
clean:
rm -rf $(TARGET)
deploy: $(TARGET)
rsync -azP --delete $(TARGET)/ $(SYSTEM):$(DEST)
serve:
$(CC) $(FLAGS) serve