Autopush - Simply Upload Changed Files
To simplify my web design / web development workflow, I wrote myself a small autopush script. The script watches a given folder and all its subfolders for changes and uploads the changed files to a remote server via SCP. So if you like to develop locally but want to push your changes straight to your server without constantly uploading manually, you'll probably like this script :) As always: no liability for damages.
Important:
- You need to authenticate against the server with an SSH key, otherwise the bash script needs minimal adjustments.
- You need to have fswatch installed.
Autopush works like this: you create an autopush config file in ini format, which is passed to the bash script as the first parameter. The autopush file is structured as follows:
remote_host=The host you want to push the files to. Can be a domain or an IP. Remember the SSH keys.remote_username=The username you authenticate with on the serverremote_mapping=The path that is mapped to. Changes in local_source are uploaded relative to remote_mapping.local_source=The local path that is to be watched and pushed.exclude=source,_ServerFiles that shouldn't be pushed and are excluded from watching.
Note: .DS_Store files are excluded programmatically and don't need to be listed explicitly.
The folder in local_source is watched by the script. As soon as a file in it changes, it is uploaded to the server via
scp local_file_path remote_username@remote_host:/remote_mapping/absolute_local_path
You can call the bash script simply via:
autopush.sh /path/to/config.ini
And here is the complete script:
#!/bin/sh
if [ $# -eq 1 ]; then
CONFIGFILE=$1
. $1
echo "Autopushing '$local_source' now..."
/usr/local/bin/fswatch -0 "$local_source" | xargs -0 -n 1 sh $0 0 $CONFIGFILE
elif [ $# -eq 2 ] && [ $2="--fullsync" ]; then
CONFIGFILE=$1
. $1
echo "Fullsyncing '$local_source' now..."
scp -r $local_source/* $remote_username@$remote_host:$remote_mapping
else
CONFIGFILE=$2
FILE=$3
. $CONFIGFILE
length_local_source=${#local_source}
length_changed_file_absolute=${#FILE}
length_changed_file_relative=$((0-length_local_source-length_changed_file_absolute))
relative_path=${FILE:$length_local_source}
donotpush=(${exclude//,/ })
donotpush+=($CONFIGFILE)
donotpush+=(".DS_Store")
for i in "${donotpush[@]}"
do
if [[ $FILE == *$i* ]]; then
echo "[STOP] DO NOT PUSH $FILE (MATCHES '$i')"
exit
fi
done
remote_target="$remote_mapping$relative_path"
if [ -d "$FILE" ] || [ -f "$FILE" ]; then
echo "[CHANGE] `date '+%Y-%m-%d %H:%M:%S'` $relative_path -> $remote_target";
scp -r $FILE $remote_username@$remote_host:$remote_target
else
echo "[DELETE] rm -rf $remote_target";
ssh $remote_username@$remote_host "rm -rf $remote_target"
fi
fi