Simplified a bit.
[xremote.git] / xremote.sh
index 7556470..bcb33ca 100755 (executable)
@@ -35,7 +35,7 @@ function check_remote_is_defined () {
 
 function help () {
     cat <<EOF
-xremote.sh [-h remote_host] <script> [script arguments]
+xremote.sh [--help] [-h <remote_host>] [-d <remote_dir>] [-r <local_result_dir>] [-i] <script> [script arguments]
 
   This script takes a script as argument and executes it remotely in a
   temporary directory on a ssh-accessible server.
@@ -56,8 +56,23 @@ xremote.sh [-h remote_host] <script> [script arguments]
     @XREMOTE_GET: *.dat
     @XREMOTE_PRE: ln -s /home/fleuret/data/pytorch ./data
 
+  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 -d option is provided, the provided directory is used and
+  kept, instead of a temporary one
+
+  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 the -r option is provided, the result files specified with
+  @XREMOTE_GET will be downloaded there instead of the current
+  directory.
+
   If no argument is provided to @XREMOTE_HOST, and the -h option is
   not specified, the environment variable \$XREMOTE_HOST is used
   instead
@@ -71,8 +86,13 @@ EOF
 function cleanup_remote_tmp () {
     if [[ "${REMOTE_HOST}" ]] && [[ "${REMOTE_DIR}" ]]
     then
-        echo "xremote: Clean up remote workdir."
-        ssh "${REMOTE_HOST}" "rm -rf \"${REMOTE_DIR}\""
+        if [[ "${ARG_DIR}" ]]
+        then
+            echo "xremote: Keeping remote workdir."
+        else
+            echo "xremote: Cleaning up temporary remote workdir."
+            ssh "${REMOTE_HOST}" rm -rf "${REMOTE_DIR}"
+        fi
     fi
 }
 
@@ -85,10 +105,36 @@ do
         -h)
             shift
             ARG_HOST="$1"
+            [[ ${ARG_HOST} ]] || (echo "xremote: Hostname missing." && exit 1)
             echo "xremote: remote forced to ${ARG_HOST}"
             ;;
+
+        -d)
+            shift
+            ARG_DIR="$1"
+            [[ ${ARG_DIR} ]] || (echo "xremote: Directory missing." && exit 1)
+            echo "xremote: remote dir set to ${ARG_DIR}"
+            ;;
+
+        -i)
+            NO_RUN=1
+            echo "xremote: no run"
+            ;;
+
+        -r)
+            shift
+            ARG_RESULT_DIR="$1"
+            [[ ${ARG_RESULT_DIR} ]] || (echo "xremote: Directory missing." && exit 1)
+            echo "xremote: result dir set to ${ARG_RESULT_DIR}"
+            ;;
+
+        --help)
+            help
+            exit 0
+            ;;
+
         *)
-            echo "Unknown option $1"
+            echo "xremote: Unknown option $1"
             exit 1
             ;;
     esac
@@ -97,12 +143,22 @@ done
 
 ######################################################################
 
-[[ -a "$1" ]] || (help && exit 1)
+[[ "$1" ]] || (echo "xremote: Script name missing" && exit 1)
 
-main="$(basename "$1")"
+[[ -a "$1" ]] || (help && echo >&2 "xremote: Cannot find script \`$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
@@ -115,8 +171,8 @@ do
     if [[ "${line}" =~ '@XREMOTE' ]]
     then
 
-        label=$(echo "${line}" | sed -e 's/^.*@XREMOTE_\([^:]*\):.*$/\1/')
-        value=$(echo "${line}" | sed -e 's/^.*@XREMOTE_[^:]*: *\(.*\)$/\1/')
+        label=$(sed -e 's/^.*@XREMOTE_\([^:]*\):.*$/\1/' <<<"${line}")
+        value=$(sed -e 's/^.*@XREMOTE_[^:]*: *\(.*\)$/\1/' <<<"${line}")
 
         case "${label}" in
 
@@ -144,13 +200,19 @@ do
                 [[ "${REMOTE_HOST}" ]] || REMOTE_HOST="${value}"
                 [[ "${REMOTE_HOST}" ]] || REMOTE_HOST="${XREMOTE_HOST}"
                 [[ "${REMOTE_HOST}" ]] || (echo "xremote: No remote host specified." >&2 && exit 1)
-                REMOTE_DIR="$(ssh </dev/null "${REMOTE_HOST}" mktemp -d /tmp/xremote.from_"$(hostname)_$(date +%Y%m%d-%H%M%S)".XXXXXX)"
+                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}"
 
 ######################################################################
 
@@ -158,6 +220,12 @@ check_remote_is_defined
 
 tar c "${main}" | ssh "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar mx"
 
+if [[ "${NO_RUN}" ]]
+then
+    echo "xremote: everything has been set up in ${REMOTE_HOST}:${ARG_DIR}"
+    exit 0
+fi
+
 echo "xremote: -- running the executable -----------------------------------"
 
 if [[ "${REMOTE_EXEC}" ]]
@@ -170,6 +238,7 @@ fi
 ######################################################################
 
 # I find this slightly ugly ...
+
 for s in "$@"
 do
   quoted_args="${quoted_args} \"${s}\""
@@ -185,12 +254,21 @@ echo "xremote: -- retrieving files -----------------------------------------"
 
 set -f
 
+if [[ "${ARG_RESULT_DIR}" ]]
+then
+    RESULT_DIR="${ARG_RESULT_DIR}"
+else
+    RESULT_DIR="."
+fi
+
+[[ "${ARG_RESULT_DIR}" ]] && mkdir -p "${ARG_RESULT_DIR}"
+
 while read line
 do
     if [[ "${line}" =~ '@XREMOTE' ]]
     then
-        label=$(echo "${line}" | sed -e 's/^.*@XREMOTE_\([^:]*\):.*$/\1/')
-        value=$(echo "${line}" | sed -e 's/^.*@XREMOTE_[^:]*: *\(.*\)$/\1/')
+        label=$(sed -e 's/^.*@XREMOTE_\([^:]*\):.*$/\1/' <<<"${line}")
+        value=$(sed -e 's/^.*@XREMOTE_[^:]*: *\(.*\)$/\1/' <<<"${line}")
         case "${label}" in
             POST)
                 check_remote_is_defined
@@ -200,11 +278,12 @@ do
 
             GET)
                 check_remote_is_defined
-                ssh </dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar 2>/dev/null c ${value}" | tar mxv
+                ssh </dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar 2>/dev/null c ${value}" | tar mxv -C "${RESULT_DIR}"
                 ;;
         esac
     fi
-done < "${main}"
+
+done < "${main_config}"
 
 set +f