Allow deleting files from a tree and SLOC halved! - drist - a remote deployment tool HTML git clone git://bitreich.org/drist/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/drist/ DIR Log DIR Files DIR Refs DIR Tags DIR README DIR LICENSE --- DIR commit c93097b6761dd565bbc876957c220e1fcc66b214 DIR parent 610f7e84667a582a83b3b12af8169169503cd6f9 HTML Author: Solene Rapenne <solene@perso.pw> Date: Thu, 19 Jul 2018 11:31:33 +0200 Allow deleting files from a tree and SLOC halved! Diffstat: M drist | 94 +++++++++++++++++-------------- M drist.1 | 85 ++++++++++++++++++++++--------- 2 files changed, 111 insertions(+), 68 deletions(-) --- DIR diff --git a/drist b/drist @@ -1,61 +1,69 @@ #!/bin/sh -if [ "$#" -ne 1 ] -then +if [ "$#" -ne 1 ]; then echo "You should pass a server as a parameter" exit 1 else HOSTNAME=$(ssh "$1" "uname -n") - if [ "$?" -ne 0 ] - then + if [ "$?" -ne 0 ]; then echo "Error while ssh ${1}" exit 2 fi fi -# -l = keep symlink / -D = special device -if [ -d "files" ] -then - LIST=$(mktemp /tmp/drist-rsync.XXXXXXXXXX) - if [ -f "$LIST" ] +# $1 = directory name +# $2 = remote server +copy_files() { + # -l = keep symlink / -D = special device + if [ -d "${1}" ] then - find files/ -type f | cut -d '/' -f 2- > "${LIST}" - printf 'Copying files :\n' ; cat $LIST - rsync -lD --files-from="${LIST}" files/ "${1}":/ - rm "$LIST" + LIST=$(mktemp /tmp/drist-rsync.XXXXXXXXXX) + if [ -f "$LIST" ] + then + printf 'Copying files:\n' + find "${1}"/ -type f | cut -d '/' -f 2- | tee "${LIST}" + rsync -lD --files-from="${LIST}" "${1}/" "${2}":/ + rm "$LIST" + fi fi -fi +} -if [ -d "files-${HOSTNAME}" ] -then - LIST=$(mktemp /tmp/drist-rsync.XXXXXXXXXX) - if [ -f "$LIST" ] +# $1 = script filename +# $2 = remote server +remote_script() { + if [ -f "${1}" ] then - find "files-${HOSTNAME}/" -type f | cut -d '/' -f 2- > "${LIST}" - printf 'Copying files only for %s:\n' "${HOSTNAME}" ; cat $LIST - rsync -lD --files-from="${LIST}" "files-${HOSTNAME}/" "${1}":/ - rm "$LIST" + printf 'Executing script\n' + cat "${1}" | \ + ssh "${2}" 'DRIST=$(mktemp /tmp/drist.XXXXXXXXXXXX) && + cat - > "$DRIST" && + chmod u+x "$DRIST" && + "$DRIST" ; + rm "$DRIST"' fi -fi +} -if [ -f "script" ] -then - printf 'Executing script\n' - cat "script" | \ - ssh "${1}" 'DRIST=$(mktemp /tmp/drist.XXXXXXXXXXXX) && - cat - > "$DRIST" && - chmod u+x "$DRIST" && - "$DRIST" ; - rm "$DRIST"' -fi +# $1 = directory name +# $2 = remote server +# it uses rm -v which is not POSIX compliant but most systems have it +delete_files() { + if [ -d "${1}" ] + then + LIST=$(mktemp /tmp/drist-rsync.XXXXXXXXXX) + if [ -f "$LIST" ] + then + printf 'Removing files:\n' + find "$1" -type f | sed 's/"/\\&/' | \ + awk -v path="${1}" '{ printf "\"%s\" ",substr($0,length(path)+1)}' > "${LIST}" + ssh "$2" "rm -v $(cat $LIST)" + fi + fi +} -if [ -f "script-${HOSTNAME}" ] -then - printf 'Executing script only for %s:\n' "${HOSTNAME}" - cat "script-${HOSTNAME}" | \ - ssh "${1}" 'DRIST=$(mktemp /tmp/drist.XXXXXXXXXXXX) && - cat - > "$DRIST" && - chmod u+x "$DRIST" && - "$DRIST" ; - rm "$DRIST"' -fi + +copy_files "files" "$1" +copy_files "files-${HOSTNAME}" "$1" +remote_script "script" "$1" +remote_script "script-${HOSTNAME}" "$1" +delete_files "absent" "$1" +delete_files "absent-${HOSTNAME}" "$1" DIR diff --git a/drist.1 b/drist.1 @@ -19,43 +19,78 @@ has been designed to be simple, so it may not offer features you want. When you run .Nm -, it will look at two special directories in the current working directory. +, it will look at special directories in the current working directory. -The first is +The whole sequence is the following, with HOSTNAME being the result of +.Ql uname -n +on the remote system. + +.Bl -enum -offset indent -compact +.It +if folder .Ar files -and the content of this folder will be copied on the remote server +exists, files in it are copied on +.Ar server +.It +if folder +.Ar files-HOSTNAME +exists, files in it are copied on +.Ar server +.It +if folder +.Ar absent +exists, files in it are removed remotely on +.Ar server +.It +if folder +.Ar absent-HOSTNAME +exists, files in it are removed remotely on .Ar server -from the root filesystem /. +.It +if file +.Ar script +exists, it is executed remotely on +.Ar server +.It +if file +.Ar script-HOSTNAME +exists, it is executed remotely on +.Ar server +.El -The second directory is -.Ar files-servername + +If directory +.Ar files +is present, the content of this folder will be copied on the remote server +.Ar server +from the root filesystem /. You can create +.Ar files-HOSTNAME with -.Ar servername +.Ar HOSTNAME being the result of the command .Ql uname -n -on the remote server. The content of this folder will be copied on the remote server -.Ar server -from the root filesystem /. This folder is useful if you need to add some files only -on certains servers. +on the remote server. The content of this foldre will be copied on the remote server +after the +.Ar files +directory. This folder is useful if you need to add some files only on certains servers. After the files are copied, .Nm -will look at two files in the current working directory. +will look at two the folders +.Ar absent +and +.Ar absent-HOSTNAME +in the current working directory. +.Nm +will remotely delete all files listed in the tree of the directory. -The first file is +Finally, the file .Ar script -and will be copied on the remote server and then executed and deleted after execution -(shall the script succeed or fail). - -The second file is -.Ar script-hostname -with -.Ar servername -being the result of the command -.Ql uname -n -, if it exists, it will be copied on the remote server and then executed and deleted after execution -(shall the script succeed or fail). This is useful if you need to run commands on a particular -servers. +be copied on the remote server and then executed and deleted after execution +(shall the script succeed or fail). If +.Ar script-HOSTNAME +exists, it will be procedded too in the same way. This is useful if you need +to run commands on a particular servers. I recommend to write small "modules" installing required packages for a task and providing the files needed rather than an all-in-one module to deploy an entire system.