alistairphillips.com

I’m : a web and mobile developer based in the Manning Valley, Australia.


File sync with fswatch and rsync

Some projects I work on require that I use a remote web server. PHPStorm is my IDE of choice and, up until now, I've had it SFTP the files to the remote host. But that has been less than ideal as it still feels slow and I could swear it isn't keeping the remote connection alive leading to quite a lag in uploads.

As a replacement I'm going to trial using fswatch to record a list of changed files which is then handed over to rsync to upload. To speed things up I configure SSH on macOS to re-use an existing session. With this enabled further connections, including rsync, are a lot snappier.

To do that edit ~/.ssh/config adding something similar to the following:

Host example.org
    ControlMaster auto
    ControlPath /tmp/%h%p%r

I then created a bash script that performs the following actions:

Now, if you keep an SSH session open elsewhere, rsync will re-use this which, when combined with the list of files to upload, should result in speedier uploads.

It's early days yet for this set up but initial tests seem promising. Shell scripting like this certainly isn't my forte so I'll be the first one to say that there's probably a lot of optimisation that could be done. But it works for me.

#!/usr/bin/env bash
rm --force /tmp/example.org-rsync.txt
rm --force /tmp/example.org-rsync-relative.txt

echo "Starting initial sync..."
rsync --verbose -azP --delete --exclude='.git/' --exclude='.idea/' --exclude='.DS_Store' --exclude='tmp/' /Users/alistair/Code/example.org/ user@example.org:/var/www/example.org
echo ""

echo "Watching..."

fswatch --exclude="___jb_" --exclude=".idea" --exclude=".git" --batch-marker=EOF -xn /Users/alistair/Code/example.org/ | while read file event; do
    if [ $file = "EOF" ]; then
       printf "%s\n"  "${list[@]}" > /tmp/example.org-rsync.txt
       sed -e "s,/Users/alistair/Code/example.org/,," /tmp/example.org-rsync.txt > /tmp/example.org-rsync-relative.txt
       echo "Beginning sync..."
       rsync --verbose --files-from=/tmp/example.org-rsync-relative.txt /Users/alistair/Code/example.org/ user@example.org:/var/www/example.org
       osascript -e 'display notification "rsync complete!" with title "example.org"'
       echo "sync completed"
       echo "Watching..."
       list=()
    else
       list+=($file)
    fi
done