#!/bin/bash # this file is meant to be sourced, not executed directly # if destination argument is not provided, fail if [[ $# -lt 1 ]]; then echo "$(basename $BASH_SOURCE): error: no destination provided!" >&2 return 1 elif [[ $# -gt 1 ]]; then echo "$(basename $BASH_SOURCE): error: too many arguments!" >&2 return 1 fi # provide sshp command for executing commands on remote computer sshp() { echo "$@" >&$_sshp_in echo "echo EOF" >&$_sshp_in sed '/EOF/Q' <$_sshp_tmpdir/out } # assign dest to variable _sshp_dest=$1 # create temporary directory _sshp_tmpdir=$(mktemp -d) mkfifo $_sshp_tmpdir/in $_sshp_tmpdir/out # assign input and output to a file descriptors so they don't get closed exec {_sshp_in}<>$_sshp_tmpdir/in {_sshp_out}<>$_sshp_tmpdir/out # trap exit to do cleanup trap "{ exec {_sshp_in}>&- {_sshp_out}>&-; ssh -O exit -S $_sshp_tmpdir/ssh $_sshp_dest &>/dev/null; rm -rf $_sshp_tmpdir; }" EXIT # login with master so ssh can ask password if necessary ssh -M -Nf -S $_sshp_tmpdir/ssh $_sshp_dest # login with redirection for the persistent connection ssh -S $_sshp_tmpdir/ssh medusa 0<&$_sshp_in 1>&$_sshp_out 2>&1 & # clear output sshp true &> /dev/null # ask for password and run sudo so password can be cached ( user=$(sshp echo \$USER) host=$(sshp hostname) askpass() { read -p "[sudo] password for $user@$host: " -s password printf "\n" >&2 echo "${password}" >&$_sshp_in } line='' while [[ $line != "[sudo] password for $user: EOF" ]]; do if [[ $line == "" ]]; then echo "sudo -S echo 'EOF'" >&$_sshp_in elif [[ $line == "[sudo] password for $user: Sorry, try again." ]]; then echo "Sorry, try again." >&2 elif [[ $line == "[sudo] password for $user: sudo: 3 incorrect password attempts" ]]; then echo "$(basename $BASH_SOURCE): 3 incorrect password attempts" >&2 return 1 else echo "$(basename $BASH_SOURCE): unexpected output during sudo: ${line@Q}" >&2 return 1 fi askpass read line <$_sshp_tmpdir/out done ) # clear output again sshp true &> /dev/null