Este é meu wrapper ssh
de propósito geral. Nenhuma opção nem endereço é codificado. A única coisa que você pode precisar ajustar é o caminho para o executável ssh
na linha 3 (você pode usar executable=ssh
, eu escolhi o caminho completo). Você encontrará meu código completo abaixo.
Digamos que você tenha salvado como sshmt
("ssh, multi target") para o qual $PATH
aponta, tornado executável com chmod
. Em seguida, familiarize-se com a sintaxe:
sshmt -h
Trecho:
USAGE
sshmt [-v] ARGS [+[N] ARGS]... [-- COMMON] sshmt -h
SYNOPSIS
Invokes
ssh
command with the first set of argumentsARGS
and common argumentsCOMMON
. If this command returns exit status of255
and the second set of argumentsARGS
exists, then the secondssh
will be invoked with these newARGS
andCOMMON
; then the third and so on.
No seu caso de exemplo, você quer invocá-lo assim:
sshmt 10.0.0.1 + my_machine.example.com + my_machine.example.com -J me@other_machine.example.com
ou melhor com alguns tempos limite convenientes:
sshmt 10.0.0.1 +2 my_machine.example.com +3 my_machine.example.com -J me@other_machine.example.com +5
Para executar remotamente df -h
de maneira simples, invoque:
sshmt 10.0.0.1 df -h +2 my_machine.example.com df -h +3 my_machine.example.com -J me@other_machine.example.com df -h +5
mas você não quer se repetir, então use isso:
sshmt 10.0.0.1 +2 my_machine.example.com +3 my_machine.example.com -J me@other_machine.example.com +5 -- df -h
Os tubos devem funcionar também:
echo 123 | sshmt 10.0.0.1 +2 my_machine.example.com +3 my_machine.example.com -J me@other_machine.example.com +5 -- sh -c "cat > /tmp/foo"
Na prática, você pode querer definir um alias:
alias myssh='sshmt 10.0.0.1 +2 my_machine.example.com +3 my_machine.example.com -J me@other_machine.example.com +5 --'
faça login com
myssh
ou execute um comando como
myssh uptime
Este é o código. Toda a sua lógica apenas analisa a linha de comando realmente.
#!/usr/bin/env bash
executable=/usr/bin/ssh
exename="${executable##*/}"
myname="${0##*/}"
declare -a args
declare -a seq_opts
declare -a common_opts
main () {
split_opts "$@"
process_seq "${seq_opts[@]}" "+"
exit 255
}
split_opts () {
while [ $# -ne 0 ]; do
if [ "$1" = "--" ]; then
shift
common_opts=("$@")
break
else
seq_opts=("${seq_opts[@]}" "$1")
shift
fi
done
}
process_seq() {
if [ "$*" = "+" ] || [ "$1" = "-h" ]; then
print_help; exit 0
fi
while [ $# -ne 0 ]; do
if [ "${1:0:1}" != "+" ]; then
args=("${args[@]}" "$1")
else
timeout="${1:1}"
[[ "$timeout" =~ ^[0-9]*$ ]] || print_error
if [ "${#args[*]}" -ne 0 ]; then
printf '%s\n' "${myname}: trying ${args[*]}" >&2
"$executable" ${timeout:+-o ConnectTimeout=$timeout} "${args[@]}" "${common_opts[@]}"
status=$?
[ $status -ne 255 ] && exit $status
args=()
fi
fi
shift
done
}
print_error() {
cat >&2 << EOF
${myname}: error parsing command line
Try '$myname -h' for more information.
EOF
exit 254
}
print_help() {
cat << EOF
USAGE
$myname [-v] ARGS [+[N] ARGS]... [-- COMMON]
$myname -h
SYNOPSIS
Invokes \'${exename}' command with the first set of arguments ARGS
and common arguments COMMON. If this command returns
exit status of 255 and the second set of arguments ARGS
exists, then the second \'ssh' will be invoked with these
new ARGS and COMMON; then the third and so on.
Empty set of arguments is discarded without invoking \'ssh'.
Successful invocation of \'ssh' stops parsing the command
line and makes the script exit.
OPTIONS
-h print this help and exit (must be the first option)
+, +N execute \'ssh' with preceding ARGS and COMMON
N, if given, specifies timeout for \'ssh' invoked with
immediately preceding ARGS. This is just a convenient
alternative for \'-o ConnectTimeout=N'.
The final set of arguments may or may not have a terminating \'+'.
EXIT STATUS
The exit status is 254 in case of an error while parsing
the command line; 255, if none of \'${exename}' managed
to connect; or an exit status of successfully connected
\'${exename}' otherwise.
EXAMPLES
To try 10.0.0.1 and, if failed, the alternative address:
$myname 10.0.0.1 + my_machine.example.com
To execute \'df -h' with timeouts:
$myname 10.0.0.1 +3 my_machine.example.com +5 -- df -h
LICENCE
Creative Commons CC0.
EOF
}
main "$@"