From 09bff4c7a267086bb2e97bfa521c2b0438def56d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 19 Feb 2019 08:06:52 +0200 Subject: Add login-machine helper script --- doc/manual.cli | 2 + login-machine | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100755 login-machine diff --git a/doc/manual.cli b/doc/manual.cli index 91dc68b..a2484aa 100644 --- a/doc/manual.cli +++ b/doc/manual.cli @@ -592,6 +592,8 @@ command: echo cont | ssh build@build socat - UNIX-CONNECT:/tmp/monitor-- \ +\N|The \c{login-machine} helper script implements this sequence of steps.| + Other useful QEMU monitor commands are \c{system_powerdown} and \c{system_reset}. diff --git a/login-machine b/login-machine new file mode 100755 index 0000000..18e1f34 --- /dev/null +++ b/login-machine @@ -0,0 +1,127 @@ +#! /usr/bin/env bash + +# Login into a machine. +# +# -c +# Execute QEMU 'cont' command in the specified machine monitor UNIX +# socket prior to logging in. +# +# - build host the machine is running on +# - machine's VNC port on the build host +# +usage="usage: $0 [-c ] " + +trap "{ exit 1; }" ERR +set -o errtrace # Trap in functions. + +function info () { echo "$*" 1>&2; } +function error () { info "$*"; exit 1; } + +mon= +cmd= + +while [ "$#" -gt 0 ]; do + case "$1" in + -c) + shift + cmd=cont + mon="$1" + shift + ;; + -*) + error "unknown option: $1" + ;; + *) + break + ;; + esac +done + +host="$1" +fport="$2" + +if [ -z "$host" -o -z "$fport" ]; then + error "$usage" +fi + +if [ -n "$cmd" -a -z "$mon" ]; then + error "$usage" +fi + +# Find an unused local port. Surprisingly, it's harder than one would expect. +# +function find_used_ports () +{ + # Use netstat(1) to find the list of port in use. + # + # Proto Recv-Q Send-Q Local Address Foreign Address State + # tcp 0 0 0.0.0.0:139 0.0.0.0:* LISTEN + # + local f="([^[:space:]]+)[[:space:]]+" + + netstat --listening --all --tcp --numeric | \ + sed -n -re "s/^$f$f$f$f.*$/\4/p" | \ + sed -n -re "s/^.+:([0-9]+)$/\1/p" | \ + sort --unique --numeric-sort +} + +function find_unused_port () +{ + local ups + ups=($(find_used_ports)) + + local lp up u + for ((lp=49152; lp < 65535; lp++)); do + u= + for up in "${ups[@]}"; do + if [ "$lp" -eq "$up" ]; then + u=true + break + fi + done + + if [ ! "$u" ]; then + echo "$lp" + return 0 + fi + done + + echo "all ports are in use" 1>&2 + return 1 +} + +lport=$(find_unused_port) + +# OpenSSH local port forwarding. +# +# ssh -L :: +# +# Forward connections on localhost: to : +# via . +# +# We are putting OpenSSH to background (-f -N) and then using the "control +# socket" mechanism (-M -S) to terminate it. This also makes sure we don't +# share any existing control sockets that may be set in .ssh/config (e.g., +# for connection caching/multiplexing). +# +csock="$(mktemp -u)" + +ssh -f -N -M -S "$csock" -L "$lport:localhost:$fport" \ + -o ExitOnForwardFailure=yes "build@$host" + +function exit_trap () +{ + # OpenSSH prints "Exit request sent." regardless of -q. + # + if ! ssh -q -S "$csock" -O exit "build@$host" 2>/dev/null; then + error "unable to terminate background ssh process via $csock" + fi +} + +trap exit_trap EXIT + +if [ -n "$cmd" ]; then + echo "$cmd" | ssh -S "$csock" "build@$host" socat - "UNIX-CONNECT:$mon" +fi + +vinagre "localhost:$lport" -- cgit v1.1