OCD cosmetics.
[xremote.git] / xremote.sh
index 59e588c..5536d01 100755 (executable)
@@ -18,7 +18,8 @@
 #########################################################################
 
 set -e
 #########################################################################
 
 set -e
-set -o pipefail
+
+# set -o pipefail
 
 ######################################################################
 
 
 ######################################################################
 
@@ -34,14 +35,14 @@ function check_remote_is_defined () {
 
 function help () {
     cat <<EOF
 
 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.
 
 
   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
   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
   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
 
     @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.
 
 
   Contact <francois@fleuret.org> for comments.
 
@@ -64,21 +77,56 @@ EOF
 }
 
 function cleanup_remote_tmp () {
 }
 
 function cleanup_remote_tmp () {
-    if [[ "${REMOTE_HOST}" ]] && [[ "${REMOTE_DIR}" ]]
+    if [[ "${REMOTE_HOST}" ]] && [[ "${REMOTE_DIR}" ]] && [[ ! "${ARG_DIR}" ]]
     then
     then
-        echo "Clean up remote workdir."
-        ssh "${REMOTE_HOST}" "rm -rf \"${REMOTE_DIR}\""
+        echo "xremote: Clean up remote workdir."
     fi
 }
 
 ######################################################################
 
     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")"
 
 
 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
 
 ######################################################################
 trap cleanup_remote_tmp EXIT
 
 ######################################################################
@@ -96,30 +144,41 @@ do
 
             EXEC)
                 check_remote_is_defined
 
             EXEC)
                 check_remote_is_defined
+                [[ "${REMOTE_EXEC}" ]] && (exit "Remote executable already defined!" >&2 && exit 1)
                 REMOTE_EXEC="${value}"
                 ;;
 
             PRE)
                 check_remote_is_defined
                 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
                 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)
                 ;;
 
             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}" ]] || 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
 
                 ;;
         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"
 
 
 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
 
 if [[ "${REMOTE_EXEC}" ]]
 then
@@ -138,13 +201,23 @@ else
     REMOTE_COMMAND="./${main}"
 fi
 
     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
 
 
 ######################################################################
 
 # Disable globbing to keep wildcards for the remote side
 
+echo "xremote: -- retrieving files -----------------------------------------"
+
 set -f
 
 while read line
 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
         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
             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
                 ;;
         esac
     fi
-done < "${main}"
+
+done < "${main_config}"
 
 set +f
 
 
 set +f
 
+echo "xremote: -- finished -------------------------------------------------"
+
 ######################################################################
 ######################################################################