URI: 
       Major rework - 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 1ddb1582cfb17a5d79fd9725907a1b329dacbd6b
   DIR parent c6481050031bc54fa99a6fcfa7d3408850040883
  HTML Author: Solene Rapenne <solene@perso.pw>
       Date:   Wed, 26 Aug 2020 21:13:06 +0200
       
       Major rework
       
       Files are now copied in a temporary subtree and files must be copied on the
       system from the script. This is safer in many ways and result is predictable.
       
       Drop "absent" function
       Drop simulate flag
       
       If previous behavior is prefered, you should stay with previous version
       
       Diffstat:
         M drist                               |     165 ++++++++++++++++---------------
         M drist.1                             |      28 +++++++++-------------------
       
       2 files changed, 94 insertions(+), 99 deletions(-)
       ---
   DIR diff --git a/drist b/drist
       @@ -1,20 +1,71 @@
        #!/bin/sh
        
       -SIMULATE=0
        SUDO=0
        SUDO_BIN=sudo
        EXEC=""
        SSHONCE=0
        TRUNCATE=0
       +TEMPDIR=""
        
        usage() {
       -        echo "$0 [-n] [-d] [-s [-e sudo|doas]] server"
       +        echo "$0 [-n] [-d] [-s [-e sudo|doas]] server [...]"
                exit 0
        }
        
       +# $1 = directory name
       +# $2 = remote server
       +copy_files() {
       +        # -l = keep symlink / -D = special device
       +        if [ -d "${1}" ]
       +        then
       +                LIST=$(mktemp /tmp/drist-rsync.XXXXXXXXXX)
       +                if [ -f "$LIST" ]
       +                then
       +                        printf 'Copying files from "%s" to temporary directory %s:\n' "$1" "$3"
       +                        find "${1}"/ -type f -or -type l | cut -d '/' -f 2- | tee "${LIST}" | sed 's/^/        \//'
       +                        rsync -e "ssh $SSH_PARAMS" -lD --files-from="${LIST}" "${1}/" "${2}":"/${3}"
       +                        rm "$LIST"
       +                fi
       +        fi
       +}
       +
       +# $1 = script filename
       +# $2 = remote server
       +# $3 = tempdir
       +remote_script() {
       +        if [ -f "${1}" ]
       +        then
       +                printf 'Executing file "%s":\n' "$1"
       +                ssh $SSH_PARAMS "${2}" "cd ${3} && DRIST=${3}/script &&
       +                    cat - > \$DRIST &&
       +                    chmod u+x \$DRIST &&
       +                    ${EXEC} \$DRIST" < "$1"
       +        fi
       +}
       +
       +# $1 = remote server
       +create_temp() {
       +    TEMPDIR=$(ssh $SSH_PARAMS "$1" "mktemp -d ~/.drist_files_XXXXXXXXXXXXXXX")
       +    if [ "$TEMPDIR" = "" ]; then
       +        echo "mktemp error, aborting"
       +    fi
       +}
       +
       +# $1 = remote server
       +# $2 = temporary directory
       +delete_temp() {
       +    if echo "${2}" | grep drist_files_ >/dev/null ; then
       +        ssh $SSH_PARAMS "$1" "rm -fr ${2}"
       +    else
       +        echo "Problem, TEMPDIR was reset during execution, current value is = $2"
       +        exit 2
       +    fi
       +}
       +
       +
       +# RUNTIME BEGINS HERE
        while getopts pndse: arg; do
                case ${arg} in
       -                n) SIMULATE=1 ;;
                        d) TRUNCATE=1 ;;
                        s) SUDO=1 ;;
                        e) SUDO_BIN="${OPTARG}" ;;
       @@ -36,93 +87,47 @@ then
                SSH_PARAMS=-o"ControlMaster=auto"" "-o"ControlPath=/tmp/drist_ssh_%h_%p_%r.sock"" "-o"ControlPersist=1m"
        fi
        
       -# check if host exists
       -if [ "$#" -ne 1 ]; then
       -        usage
       +# start looping over server list
       +if [ -f "$1" ]
       +then
       +        SERVER_LIST="$(cat $1 | tr '\n' ' ')"
        else
       -        HOSTNAME=$(ssh $SSH_PARAMS "$1" "${EXEC} uname -n")
       +        SERVER_LIST="$@"
       +fi
       +
       +if [ "${SERVER_LIST}" = "" ]
       +then
       +        echo "No server specified"
       +        exit 1
       +fi
       +
       +for remote_server in ${SERVER_LIST}
       +do
       +        echo "Running on ${remote_server}"
       +
       +        # check if host exists
       +        HOSTNAME=$(ssh $SSH_PARAMS "${remote_server}" "${EXEC} uname -n")
                if [ "$?" -ne 0 ]; then
       -                echo "Error while ssh ${1}"
       +                echo "Error while ssh ${remote_server}"
                        exit 2
                fi
        
                if [ "$TRUNCATE" -eq 1 ]; then
                        HOSTNAME="${HOSTNAME%%.*}"
                fi
       -fi
       -
       -# $1 = directory name
       -# $2 = remote server
       -copy_files() {
       -        # -l = keep symlink / -D = special device
       -        if [ -d "${1}" ]
       -        then
       -                LIST=$(mktemp /tmp/drist-rsync.XXXXXXXXXX)
       -                if [ -f "$LIST" ]
       -                then
       -                        printf 'Copying files from folder "%s":\n' "$1"
       -                        find "${1}"/ -type f -or -type l | cut -d '/' -f 2- | tee "${LIST}" | sed 's/^/        \//'
       -                        if [ "$SIMULATE" -ne 1 ]
       -                        then
       -                                rsync -e "ssh $SSH_PARAMS" --rsync-path="${EXEC} rsync" -lDp --files-from="${LIST}" "${1}/" "${2}":/
       -                        fi
       -                        rm "$LIST"
       -                fi
       -        fi
       -}
        
       -# $1 = script filename
       -# $2 = remote server
       -remote_script() {
       -        if [ -f "${1}" ]
       -        then
       -                printf 'Executing file "%s":\n' "$1"
       -                if [ "$SIMULATE" -ne 1 ]
       -                then
       -                        dr="$(mktemp ./drist.XXXXXXXXXXXX)"
       -                        ssh $SSH_PARAMS "${2}" "DRIST=${dr} &&
       -                            cat - > \$DRIST &&
       -                            chmod u+x \$DRIST &&
       -                            ${EXEC} \$DRIST ;
       -                            rm \$DRIST" < "$1"
       -                        rm "$dr"
       -                fi
       -        fi
       -}
       +        create_temp "${remote_server}"
       +        copy_files "files" "${remote_server}" "$TEMPDIR"
       +        copy_files "files-${HOSTNAME}" "${remote_server}" "$TEMPDIR"
       +        remote_script "script" "${remote_server}" "$TEMPDIR"
       +        remote_script "script-${HOSTNAME}" "${remote_server}" "$TEMPDIR"
       +        delete_temp "${remote_server}" "$TEMPDIR"
        
       -# $1 = directory name
       -# $2 = remote server
       -delete_files() {
       -        if [ -d "${1}" ]
       +        # close socket if persistance is actived
       +        if [ "$SSHONCE" -eq 1 ]
                then
       -                LIST=$(mktemp /tmp/drist-rsync.XXXXXXXXXX)
       -                if [ -f "$LIST" ]
       -                then
       -                        printf 'Removing files from folder "%s":\n' "$1"
       -                        find "$1" -type f | sed 's/"/\\&/' | \
       -                                awk -v path="${1}" '{ printf "\"%s\" ",substr($0,length(path)+1)}' | \
       -                                tee "${LIST}" | sed 's/^/        /'
       -                        printf '\n' # add a new line
       -
       -                        if [ "$SIMULATE" -ne 1 ]
       -                        then
       -                                test -s "$LIST" && ssh $SSH_PARAMS "$2" "${EXEC} rm $(cat $LIST)"
       -                        fi
       -                        rm $LIST
       -                fi
       +                ssh $SSH_PARAMS -O exit -N "$1"
                fi
       -}
       -
       -
       -copy_files "files" "$1"
       -copy_files "files-${HOSTNAME}" "$1"
       -delete_files "absent" "$1"
       -delete_files "absent-${HOSTNAME}" "$1"
       -remote_script "script" "$1"
       -remote_script "script-${HOSTNAME}" "$1"
        
       -# close socket if persistance is actived
       -if [ "$SSHONCE" -eq 1 ]
       -then
       -        ssh $SSH_PARAMS -O exit -N "$1"
       -fi
       +        unset TEMPDIR HOSTNAME
       +done
   DIR diff --git a/drist.1 b/drist.1
       @@ -10,7 +10,7 @@
        .Op Fl n
        .Op Fl d
        .Op Fl s Op Fl e Ar sudo|doas
       -.Ar server
       +.Ar server ...
        .Sh OPTIONS
        .Op Fl p
        to use persistent ssh connection, allowing to ssh only once
       @@ -59,41 +59,33 @@ by calling
        After that following steps will be executed:
        .Bl -enum -offset indent -compact
        .It
       -If folder
       +If directory
        .Ar files
        exists, its content is copied to
        .Ar server
        using
       -.Xr rsync 1 .
       +.Xr rsync 1
       +in a temporary directory in ~/.drist_files_XXXXXXXX
        .It
       -If folder
       +If directory
        .Ar files- Ns Em HOSTNAME
        exists, its content is copied to
        .Ar server
        using
       -.Xr rsync 1 .
       -.It
       -If folder
       -.Ar absent
       -exists, filenames in it are deleted on
       -.Ar server .
       -.It
       -If folder
       -.Ar absent- Ns Em HOSTNAME
       -exists, filenames in it are deleted on
       -.Ar server .
       +.Xr rsync 1
       +in a temporary directory in ~/.drist_files_XXXXXXXX .
        .It
        If file
        .Ar script
        exists, it is copied to
        .Ar server
       -and executed there.
       +and executed from the temporary directory.
        .It
        If file
        .Ar script- Ns Em HOSTNAME
        exists, it is copied to
        .Ar server
       -and executed there.
       +and executed from the temporary directory.
        .El
        .Pp
        The presence of each of those files or directories is optional.
       @@ -101,8 +93,6 @@ The presence of each of those files or directories is optional.
        All files in either
        .Ar files
        or
       -.Ar absent
       -or
        .Ar files- Ns Em HOSTNAME
        etc. are relative to the root (/) directory.
        The specific files for