3 #########################################################################
4 # This program is free software: you can redistribute it and/or modify #
5 # it under the terms of the version 3 of the GNU General Public License #
6 # as published by the Free Software Foundation. #
8 # This program is distributed in the hope that it will be useful, but #
9 # WITHOUT ANY WARRANTY; without even the implied warranty of #
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
11 # General Public License for more details. #
13 # You should have received a copy of the GNU General Public License #
14 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
16 # Written by and Copyright (C) Francois Fleuret #
17 # Contact <francois@fleuret.org> for comments & bug reports #
18 #########################################################################
24 ######################################################################
26 function check_remote_is_defined () {
27 if [[ "${REMOTE_HOST}" ]] && [[ "${REMOTE_DIR}" ]]
31 echo "@XREMOTE_HOST should come first." >&2
38 xremote.sh [-h remote_host] <script> [script arguments]
40 This script takes a script as argument and executes it remotely in a
41 temporary directory on a ssh-accessible server.
43 It parses the script first to find embedded arguments which define
44 the hostname on which to run, the files to send, the files to get
45 back when the execution is over, and commands to execute before
46 running the executable remotely.
48 These arguments can appear multiple times, except the one that
49 specifies the remote host.
53 @XREMOTE_HOST: elk.fleuret.org
54 @XREMOTE_EXEC: python3
55 @XREMOTE_SEND: main.cf
57 @XREMOTE_PRE: ln -s /home/fleuret/data/pytorch ./data
59 If the -h option is provided @XREMOTE_HOST is ignored.
61 If no argument is provided to @XREMOTE_HOST, and the -h option is
62 not specified, the environment variable \$XREMOTE_HOST is used
65 Contact <francois@fleuret.org> for comments.
71 function cleanup_remote_tmp () {
72 if [[ "${REMOTE_HOST}" ]] && [[ "${REMOTE_DIR}" ]]
74 echo "xremote: Clean up remote workdir."
75 ssh "${REMOTE_HOST}" "rm -rf \"${REMOTE_DIR}\""
79 ######################################################################
81 while [[ "$1" =~ ^- ]]
88 echo "xremote: remote forced to ${ARG_HOST}"
91 echo "Unknown option $1"
98 ######################################################################
100 [[ -a "$1" ]] || (help && exit 1)
102 main="$(basename "$1")"
108 trap cleanup_remote_tmp EXIT
110 ######################################################################
115 if [[ "${line}" =~ '@XREMOTE' ]]
118 label=$(echo "${line}" | sed -e 's/^.*@XREMOTE_\([^:]*\):.*$/\1/')
119 value=$(echo "${line}" | sed -e 's/^.*@XREMOTE_[^:]*: *\(.*\)$/\1/')
124 check_remote_is_defined
125 [[ "${REMOTE_EXEC}" ]] && (exit "Remote executable already defined!" >&2 && exit 1)
126 REMOTE_EXEC="${value}"
130 check_remote_is_defined
131 echo "xremote: ${value}"
132 ssh < /dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && ${value}"
136 check_remote_is_defined
137 echo "xremote: -- sending files --------------------------------------------"
138 tar ch ${value} | ssh "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar mxv"
142 [[ "${REMOTE_DIR}" ]] && (exit "Remote host already defined!" >&2 && exit 1)
143 REMOTE_HOST="${ARG_HOST}" # Host given in argument has priority
144 [[ "${REMOTE_HOST}" ]] || REMOTE_HOST="${value}"
145 [[ "${REMOTE_HOST}" ]] || REMOTE_HOST="${XREMOTE_HOST}"
146 [[ "${REMOTE_HOST}" ]] || (echo "xremote: No remote host specified." >&2 && exit 1)
147 REMOTE_DIR="$(ssh </dev/null "${REMOTE_HOST}" mktemp -d /tmp/xremote.from_"$(hostname)_$(date +%Y%m%d-%H%M%S)".XXXXXX)"
148 echo "xremote: target is ${REMOTE_HOST}"
155 ######################################################################
157 check_remote_is_defined
159 tar c "${main}" | ssh "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar mx"
161 echo "xremote: -- running the executable -----------------------------------"
163 if [[ "${REMOTE_EXEC}" ]]
165 REMOTE_COMMAND="${REMOTE_EXEC} ${main}"
167 REMOTE_COMMAND="./${main}"
170 ######################################################################
172 # I find this slightly ugly ...
175 quoted_args="${quoted_args} \"${s}\""
178 ssh </dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && ${REMOTE_COMMAND} ${quoted_args}"
180 ######################################################################
182 # Disable globbing to keep wildcards for the remote side
184 echo "xremote: -- retrieving files -----------------------------------------"
190 if [[ "${line}" =~ '@XREMOTE' ]]
192 label=$(echo "${line}" | sed -e 's/^.*@XREMOTE_\([^:]*\):.*$/\1/')
193 value=$(echo "${line}" | sed -e 's/^.*@XREMOTE_[^:]*: *\(.*\)$/\1/')
196 check_remote_is_defined
197 echo "xremote: ${value}"
198 ssh < /dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && ${value}"
202 check_remote_is_defined
203 ssh </dev/null "${REMOTE_HOST}" "cd \"${REMOTE_DIR}\" && tar 2>/dev/null c ${value}" | tar mxv
211 echo "xremote: -- finished -------------------------------------------------"
213 ######################################################################