Initial commit
authorFrancois Fleuret <francois@fleuret.org>
Sat, 27 May 2017 20:43:13 +0000 (22:43 +0200)
committerFrancois Fleuret <francois@fleuret.org>
Sat, 27 May 2017 20:43:13 +0000 (22:43 +0200)
xremote.sh [new file with mode: 0755]

diff --git a/xremote.sh b/xremote.sh
new file mode 100755 (executable)
index 0000000..9b753e0
--- /dev/null
@@ -0,0 +1,150 @@
+#!/bin/bash
+
+#########################################################################
+# This program is free software: you can redistribute it and/or modify  #
+# it under the terms of the version 3 of the GNU General Public License #
+# as published by the Free Software Foundation.                         #
+#                                                                       #
+# This program is distributed in the hope that it will be useful, but   #
+# WITHOUT ANY WARRANTY; without even the implied warranty of            #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      #
+# General Public License for more details.                              #
+#                                                                       #
+# You should have received a copy of the GNU General Public License     #
+# along with this program. If not, see <http://www.gnu.org/licenses/>.  #
+#                                                                       #
+# Written by and Copyright (C) Francois Fleuret                         #
+# Contact <francois@fleuret.org> for comments & bug reports             #
+#########################################################################
+
+set -e
+set -o pipefail
+
+######################################################################
+
+function check_remote_is_defined () {
+    if [[ "${REMOTE_HOST}" ]] && [[ "${REMOTE_DIR}" ]]
+    then
+        return 0
+    else
+        echo "@XREMOTE_HOST should come first." >&2
+        exit 1
+    fi
+}
+
+function help () {
+    cat <<EOF
+xremote.sh <executable>
+
+  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
+  running the executable remotely.
+
+  These arguments can appear multiple times, except the one that
+  specifies the remote host.
+
+  Example:
+
+    @XREMOTE_HOST: elk.fleuret.org
+    @XREMOTE_SEND: mnist.py
+    @XREMOTE_GET: *.dat
+    @XREMOTE_PRE: ln -s /home/fleuret/data/pytorch ./data
+
+ Contact <francois@fleuret.org> for comments.
+
+EOF
+    return 0
+}
+
+function cleanup_remote_tmp () {
+    if [[ "${REMOTE_HOST}" ]] && [[ "${REMOTE_DIR}" ]]
+    then
+        echo "Clean up remote workdir."
+        ssh "${REMOTE_HOST}" "rm -rf \"${REMOTE_DIR}\""
+    fi
+}
+
+######################################################################
+
+[[ -x "$1" ]] || (help && exit 1)
+
+main="$(basename "$1")"
+
+cd "$(dirname "$1")"
+
+trap cleanup_remote_tmp EXIT
+
+######################################################################
+
+while read line
+do
+
+    if [[ "${line}" =~ '@XREMOTE' ]]
+    then
+
+        label=$(echo "${line}" | sed -e 's/^.*@XREMOTE_\([^:]*\):.*$/\1/')
+        value=$(echo "${line}" | sed -e 's/^.*@XREMOTE_[^:]*: *\(.*\)$/\1/')
+
+        case "${label}" in
+
+            PRE)
+                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"
+                ;;
+
+            HOST)
+                [[ "${REMOTE_DIR}" ]] && (exit "Remote host already defined!" >&2 && exit 1)
+                cleanup_remote_tmp
+                REMOTE_HOST=${value}
+                REMOTE_DIR="$(ssh </dev/null "${REMOTE_HOST}" mktemp -d /tmp/xremote.from_"$(hostname)_$(date +%Y%m%d)".XXXXXX)"
+                ;;
+        esac
+    fi
+
+done < "${main}"
+
+######################################################################
+
+check_remote_is_defined
+
+tar c "${main}" | ssh "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar mx"
+
+echo "----------------------------------------------------------------------"
+echo "-- On ${REMOTE_HOST}"
+echo "----------------------------------------------------------------------"
+ssh </dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && ./$(basename "${main}")"
+echo "----------------------------------------------------------------------"
+
+######################################################################
+
+# Disable globbing to keep wildcards for the remote side
+
+set -f
+
+while read line
+do
+    if [[ "${line}" =~ '@XREMOTE' ]]
+    then
+        label=$(echo "${line}" | sed -e 's/^.*@XREMOTE_\([^:]*\):.*$/\1/')
+        value=$(echo "${line}" | sed -e 's/^.*@XREMOTE_[^:]*: *\(.*\)$/\1/')
+        case "${label}" in
+            GET)
+                check_remote_is_defined
+                ssh </dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar c ${value}" | tar mxv
+                ;;
+        esac
+    fi
+done < "${main}"
+
+set +f
+
+######################################################################