OCD cosmetics.
[xremote.git] / xremote.sh
index 59e588c..5536d01 100755 (executable)
@@ -18,7 +18,8 @@
 #########################################################################
 
 set -e
-set -o pipefail
+
+# set -o pipefail
 
 ######################################################################
 
@@ -34,14 +35,14 @@ function check_remote_is_defined () {
 
 function help () {
     cat <<EOF
-xremote.sh <script>
+xremote.sh [-h <remote_host>] [-i <remote_dir>] <script> [script arguments]
 
   This script takes a script as argument and executes it remotely in a
   temporary directory on a ssh-accessible server.
 
-  It parses the script first to find embedded arguments which defines
-  the hostname on which to run it, the files to send, the files to
-  get back when the execution is done, and commands to execute before
+  It parses the script first to find embedded arguments which define
+  the hostname on which to run, the files to send, the files to get
+  back when the execution is over, and commands to execute before
   running the executable remotely.
 
   These arguments can appear multiple times, except the one that
@@ -50,12 +51,24 @@ xremote.sh <script>
   Example:
 
     @XREMOTE_HOST: elk.fleuret.org
-    @XREMOTE_SEND: mnist.py
+    @XREMOTE_EXEC: python3
+    @XREMOTE_SEND: main.cf
     @XREMOTE_GET: *.dat
     @XREMOTE_PRE: ln -s /home/fleuret/data/pytorch ./data
 
-  If no argument is provided to @XREMOTE_HOST, the environment
-  variable $XREMOTE_HOST is used instead
+  If a file with the same name as the script with the .xremote
+  extension appended to it exists, arguments will be read from it by
+  default.
+
+  If the -h option is provided @XREMOTE_HOST is ignored.
+
+  If the -i option is provided, all the files are installed and
+  scripts run in the specified directory on the remote host, but the
+  main executable and post-run commands are ignored
+
+  If no argument is provided to @XREMOTE_HOST, and the -h option is
+  not specified, the environment variable \$XREMOTE_HOST is used
+  instead
 
   Contact <francois@fleuret.org> for comments.
 
@@ -64,21 +77,56 @@ EOF
 }
 
 function cleanup_remote_tmp () {
-    if [[ "${REMOTE_HOST}" ]] && [[ "${REMOTE_DIR}" ]]
+    if [[ "${REMOTE_HOST}" ]] && [[ "${REMOTE_DIR}" ]] && [[ ! "${ARG_DIR}" ]]
     then
-        echo "Clean up remote workdir."
-        ssh "${REMOTE_HOST}" "rm -rf \"${REMOTE_DIR}\""
+        echo "xremote: Clean up remote workdir."
     fi
 }
 
 ######################################################################
 
-[[ -x "$1" ]] || (help && exit 1)
+while [[ "$1" =~ ^- ]]
+do
+    case "$1"
+    in
+        -h)
+            shift
+            ARG_HOST="$1"
+            echo "xremote: remote forced to ${ARG_HOST}"
+            ;;
+
+        -i)
+            shift
+            ARG_DIR="$1"
+            echo "xremote: remote dir set to ${ARG_DIR}"
+            ;;
+
+        *)
+            echo "Unknown option $1"
+            exit 1
+            ;;
+    esac
+    shift
+done
 
-main="$(basename "$1")"
+######################################################################
+
+[[ -a "$1" ]] || (help && echo >&2 "Cannot find $1" && exit 1)
 
 cd "$(dirname "$1")"
 
+main="$(basename "$1")"
+main_config="${main}.xremote"
+
+if [[ -f "${main_config}" ]]
+then
+    echo "xremote: found ${main_config}"
+else
+    main_config="${main}"
+fi
+
+shift
+
 trap cleanup_remote_tmp EXIT
 
 ######################################################################
@@ -96,30 +144,41 @@ do
 
             EXEC)
                 check_remote_is_defined
+                [[ "${REMOTE_EXEC}" ]] && (exit "Remote executable already defined!" >&2 && exit 1)
                 REMOTE_EXEC="${value}"
                 ;;
 
             PRE)
                 check_remote_is_defined
+                echo "xremote: ${value}"
                 ssh < /dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && ${value}"
                 ;;
 
             SEND)
                 check_remote_is_defined
-                tar c "${value}" | ssh "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar mx"
+                echo "xremote: -- sending files --------------------------------------------"
+                tar ch ${value} | ssh "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar mxv"
                 ;;
 
             HOST)
                 [[ "${REMOTE_DIR}" ]] && (exit "Remote host already defined!" >&2 && exit 1)
-                REMOTE_HOST="${value}"
+                REMOTE_HOST="${ARG_HOST}" # Host given in argument has priority
+                [[ "${REMOTE_HOST}" ]] || REMOTE_HOST="${value}"
                 [[ "${REMOTE_HOST}" ]] || REMOTE_HOST="${XREMOTE_HOST}"
-                [[ "${REMOTE_HOST}" ]] || (echo "No remote host specified." >&2 && exit 1)
-                REMOTE_DIR="$(ssh </dev/null "${REMOTE_HOST}" mktemp -d /tmp/xremote.from_"$(hostname)_$(date +%Y%m%d)".XXXXXX)"
+                [[ "${REMOTE_HOST}" ]] || (echo "xremote: No remote host specified." >&2 && exit 1)
+                if [[ "${ARG_DIR}" ]]
+                then
+                    ssh </dev/null "${REMOTE_HOST}" "mkdir -p \"${ARG_DIR}\""
+                    REMOTE_DIR="${ARG_DIR}"
+                else
+                    REMOTE_DIR="$(ssh </dev/null "${REMOTE_HOST}" mktemp -d /tmp/xremote_\$\(whoami\)_from_"$(hostname)_$(date +%Y%m%d_%H%M%S)".XXXXXX)"
+                fi
+                echo "xremote: target is ${REMOTE_HOST}"
                 ;;
         esac
     fi
 
-done < "${main}"
+done < "${main_config}"
 
 ######################################################################
 
@@ -127,9 +186,13 @@ check_remote_is_defined
 
 tar c "${main}" | ssh "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar mx"
 
-echo "----------------------------------------------------------------------"
-echo "-- On ${REMOTE_HOST}"
-echo "----------------------------------------------------------------------"
+if [[ "${ARG_DIR}" ]]
+then
+    echo "xremote: everything has been set up in ${REMOTE_HOST}:${ARG_DIR}"
+    exit 0
+fi
+
+echo "xremote: -- running the executable -----------------------------------"
 
 if [[ "${REMOTE_EXEC}" ]]
 then
@@ -138,13 +201,23 @@ else
     REMOTE_COMMAND="./${main}"
 fi
 
-ssh </dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && ${REMOTE_COMMAND}"
-echo "----------------------------------------------------------------------"
+######################################################################
+
+# I find this slightly ugly ...
+
+for s in "$@"
+do
+  quoted_args="${quoted_args} \"${s}\""
+done
+
+ssh </dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && ${REMOTE_COMMAND} ${quoted_args}"
 
 ######################################################################
 
 # Disable globbing to keep wildcards for the remote side
 
+echo "xremote: -- retrieving files -----------------------------------------"
+
 set -f
 
 while read line
@@ -154,14 +227,23 @@ do
         label=$(echo "${line}" | sed -e 's/^.*@XREMOTE_\([^:]*\):.*$/\1/')
         value=$(echo "${line}" | sed -e 's/^.*@XREMOTE_[^:]*: *\(.*\)$/\1/')
         case "${label}" in
+            POST)
+                check_remote_is_defined
+                echo "xremote: ${value}"
+                ssh < /dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && ${value}"
+                ;;
+
             GET)
                 check_remote_is_defined
-                ssh </dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar c ${value}" | tar mxv
+                ssh </dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar 2>/dev/null c ${value}" | tar mxv
                 ;;
         esac
     fi
-done < "${main}"
+
+done < "${main_config}"
 
 set +f
 
+echo "xremote: -- finished -------------------------------------------------"
+
 ######################################################################