summaryrefslogtreecommitdiff
path: root/debvm-waitssh
diff options
context:
space:
mode:
Diffstat (limited to 'debvm-waitssh')
-rwxr-xr-xdebvm-waitssh144
1 files changed, 144 insertions, 0 deletions
diff --git a/debvm-waitssh b/debvm-waitssh
new file mode 100755
index 0000000..4d69657
--- /dev/null
+++ b/debvm-waitssh
@@ -0,0 +1,144 @@
+#!/bin/sh
+# Copyright 2023 Helmut Grohne <helmut@subdivi.de>
+# SPDX-License-Identifier: MIT
+
+: <<'POD2MAN'
+=head1 NAME
+
+debvm-waitssh - Wait for a ssh server to be reachable
+
+=head1 SYNOPSIS
+
+B<debvm-waitssh> [B<-t> I<timeout>] [I<hostname>:]I<port>
+
+=head1 DESCRIPTION
+
+B<debvm-waitssh> can be used to wait for a virtual machine with exposed ssh port to be reachable on that port.
+If no hostname is given, B<127.0.0.1> is assumed.
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-t> I<timeout>, B<--timeout>=I<timeout>
+
+Set the maximum duration for waiting in seconds.
+Defaults to one minute.
+
+=back
+
+=head1 EXIT VALUES
+
+=over 8
+
+=item B<0>
+
+The server is reachable.
+
+=item B<1>
+
+A timeout was reached before the server answered.
+
+=item B<2>
+
+Usage error.
+
+=back
+
+=head1 SEE ALSO
+
+ debvm-run(1)
+
+=cut
+POD2MAN
+
+set -u
+
+TOTALTIMEOUT=60
+SCANTIMEOUT=10
+SCANDELAY=1
+
+nth_arg() {
+ shift "$1"
+ printf "%s" "$1"
+}
+
+die() {
+ echo "$*" >&2
+ exit 2
+}
+usage() {
+ die "usage: $0 [-t <timeout>] [<host>:]<port>"
+}
+usage_error() {
+ echo "error: $*" >&2
+ usage
+}
+
+opt_timeout() {
+ TOTALTIMEOUT=$1
+}
+
+while getopts :t:-: OPTCHAR; do
+ case "$OPTCHAR" in
+ t) opt_timeout "$OPTARG" ;;
+ -)
+ case "$OPTARG" in
+ help)
+ usage
+ ;;
+ timeout)
+ test "$OPTIND" -gt "$#" && usage_error "missing argument for --$OPTARG"
+ "opt_$OPTARG" "$(nth_arg "$OPTIND" "$@")"
+ OPTIND=$((OPTIND+1))
+ ;;
+ timeout=)
+ "opt_${OPTARG%%=*}" "${OPTARG#*=}"
+ ;;
+ *)
+ usage_error "unrecognized option --$OPTARG"
+ ;;
+ esac
+ ;;
+ :)
+ usage_error "missing argument for -$OPTARG"
+ ;;
+ '?')
+ usage_error "unrecognized option -$OPTARG"
+ ;;
+ *)
+ die "internal error while parsing command options, please report a bug"
+ ;;
+ esac
+done
+shift "$((OPTIND - 1))"
+
+test "$#" = 1 || usage
+
+case "$1" in
+ "")
+ usage
+ ;;
+ *:*)
+ HOST=${1%:*}
+ PORT=${1##*:}
+ ;;
+ *)
+ HOST=127.0.0.1
+ PORT=$1
+ ;;
+esac
+
+now=$(date +%s)
+deadline=$((now + TOTALTIMEOUT))
+while test "$now" -lt "$deadline"; do
+ start=$now
+ ssh-keyscan -t rsa -T "$SCANTIMEOUT" -p "$PORT" "$HOST" >/dev/null 2>&1 && exit 0
+ now=$(date +%s)
+ if test "$((now - start))" -lt "$SCANTIMEOUT"; then
+ sleep "$SCANDELAY"
+ now=$(date +%s)
+ fi
+done
+exit 1
+