Things only get slightly more complicated when you have a bastion server that must be used.
You can pass
ssh as the command to
ssh like so:
cat local_script.sh | ssh -A usera@bastion ssh -A userb@privateserver "cat > remote_copy_of_local_script.sh; bash remote_copy_of_local_script.sh"
Beware of pseudo-terminals
Note that the point of key importance here is that
ssh, like most tools, just treats
stdin correct by default.
However, when you start to see option like
Disable pseudo-terminal allocation. and
Force pseudo-terminal allocation. you may need to do a little trial and error. But, as a general rule you don't want to alter
tty behavior unless you are trying to fix garbled/binary junk in a terminal emulator (what a human types in).
For example, I tend to use
-At so that my workstation's ssh-agent gets forwarded, and so that running tmux remotely doesn't barf binary (like so
ssh -At bastion.internal tmux -L bruno attach). And, for docker too (like so
sudo docker exec -it jenkins bash).
However, those two
-t flags cause some hard to track down data corruption when I try to do something like this:
# copy /etc/init from jenkins to /tmp/init in testjenkins running as a container
ssh -A bastion.internal \
ssh -A jenkins.internal \
sudo tar cf - -C /etc init | \
sudo docker exec -i testjenkins \
bash -c 'tar xvf - -C /tmp'
# note trailing slashes to make this oneliner more readable.