I want to execute a bash script remotely which consumes a tarball and performs some logic to it. The trick is that I want to use only one ssh command to do it (rather than scp
for the tarball followed by ssh
for the script).
The bash script looks like this:
cd /tmp
tar -zx
./archive/some_script.sh
rm -r archive
I realize that I can simply reformat this script into a one-liner and use
tar -cz ./archive | ssh $HOST bash -c '<commands>'
but my actual script is complicated enough that I must pipe it to bash
via stdin. The challenge here is that ssh
provides only one input pipe (stdin) which I want to use for both the bash script and the tarball.
I came up with two solutions, both of which include the bash script and the tarball in stdin.
1. Embed base64-encoded tarball in a heredoc
In this case the server receives a bash script with the tarball is embedded inside a heredoc:
Here's the complete example:
In this approach however,
tar
does not start extracting the tarball until it is fully transferred over the network.2. Feed tar binary data after the script
In this case the bash script is piped into stdin followed by the raw tarball data.
bash
passes control totar
which processes the tar portion of stdin:Unlike the first approach, this one allows
tar
to start extracting the tarball as it is being transferred over the network.Side note
Why do we need the
main
function, you ask? Why feed the entire bash script first, followed by binary tar data? Well, if the binary data were put in the middle of the bash script, there would be an error sincetar
consumes past the end of the tarfile, which in this case would eat up some of the bash script. So, themain
function is used to force the whole bash script to come before the tar data.