Skip to content

Instantly share code, notes, and snippets.

@joshperry
Created August 9, 2016 01:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshperry/f80541245a95a7d82dfdf10ca38318d8 to your computer and use it in GitHub Desktop.
Save joshperry/f80541245a95a7d82dfdf10ca38318d8 to your computer and use it in GitHub Desktop.
# Requirements for both hosts: bash, ssh, netcat
PIPE_PORT=8842
TMPDIR=$(mktemp -d)
REQ=$TMPDIR/in
REQO=$TMPDIR/out
DEBUG_LOG=true
trap 'rm -rf "$TMPDIR"' EXIT INT TERM HUP
log () {
if [[ $DEBUG_LOG = true ]]; then echo "$1" >&2; fi
}
# Initiates the marshal connection and bootstraps the execution queue
marshalconnect () {
# Create stdin/stdout and back-pipe fifos for the remote execution queue
mkfifo $REQ
mkfifo $REQO
log "ssh fifo setup: $REQ"
# The remote execution queue is bash accepting commands over an ssh connection.
# Redirect stdin to a fifo and fork ssh
# TODO: use stdout for communicating exit codes?
ssh -qC -R $PIPE_PORT:localhost:$PIPE_PORT < $REQ > $REQO $1 /bin/bash &
SSH_PID=$!
# Open stdin and stdout fifos for REQ
log "Opening REQ fifos"
exec 3>$REQ
exec 4<$REQO
# Bootstrap the execution queue
log "bootstrapping"
echo "PIPE_PORT=$PIPE_PORT; $(declare -f log bootstrap); bootstrap" > $REQ
log "REQ started"
}
# Bootstrap function that runs on the remote execution queue to
# set up the execution environment
bootstrap () {
local tmpdir=$(mktemp -d)
BPIPE=$tmpdir/back
trap 'rm -rf "$tmpdir"' EXIT INT TERM HUP
# Create a fifo for use by the two-way netcat pipe
mkfifo $BPIPE
}
# Tell the remote session to terminate and then kill our ssh tunnel
marshaldisconnect () {
echo 'exit 0' > $REQ
}
marshal () {
# Wrap the command and args sent to this function ($@) to pipe our
# stdin/stdout over a two-way netcat
local cmd="$@ <\$BPIPE | nc localhost $PIPE_PORT >\$BPIPE"
#local cmd; printf -v cmd "%q " "$@"; cmd+=" <\$BPIPE | nc localhost $PIPE_PORT >\$BPIPE"
local funcname=$1
# If funcname is a function then define the function on the remote end before executing it
if [ "$(type -t $funcname)" = function ]; then
cmd="$(declare -f $funcname); $cmd"
fi
# Send the command to the execution queue
log "Command Start: $cmd"
echo "$cmd" > $REQ
# The remote command connects to this waiting netcat to pipe our stdin/stdout
# over the ssh forwarded port. This will block until the remote command terminates
# and closes the netcat connection.
#
# Stderr is kindly transported by the ssh process for us
log "Command Run"
nc -l $PIPE_PORT
log "Command Complete"
}
#!/bin/bash
. marshal.sh
marshalconnect $1
marshal BLAH='blah'
marshal 'echo $BLAH'
marshaldisconnect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment