Skip to content

Instantly share code, notes, and snippets.

@tubaman
Last active June 27, 2019 22:39
Show Gist options
  • Save tubaman/099b3b01a6c78bdb2110d712cc2a171c to your computer and use it in GitHub Desktop.
Save tubaman/099b3b01a6c78bdb2110d712cc2a171c to your computer and use it in GitHub Desktop.
Script to connect from one linux desktop to another using VNC over ssh
#!/bin/bash
# Connect from one linux desktop to another using SSH over VNC
#
# The script works best if you have ssh public key authentication setup with
# an agent so you don't have to type your ssh password 1000 times.
#
# Usage: vncssh remote_servername
#
# What does this do?
# 1. Calculate the right scale factor so the remote desktop resolution will
# fit on the local desktop's screen.
# 2. Start x11vnc on the remote desktop and LocalForward that VNC port back to
# the local desktop.
# 3. Use vncviewer on the local desktop to connect to x11vnc on the remote
# desktop via the ssh LocalForward.
#
# print line number on error
# https://gist.github.com/Integralist/74fffc52bb68e2bcd738
error() {
local parent_lineno="$1"
local message="$2"
local code="${3:-1}"
if [[ -n "$message" ]] ; then
echo "Error on or near line ${parent_lineno}: ${message}; exiting with status ${code}"
else
echo "Error on or near line ${parent_lineno}; exiting with status ${code}"
fi
exit "${code}"
}
trap 'error ${LINENO}' ERR
REMOTEHOST=$1
[ -n "$REMOTEHOST" ]
REMOTEDISPLAY=:0
function find_local_available_desktop {
for port in $(seq 1 99); do
if ! netstat -antu | awk '{ print $4 }' | grep -q 59$(printf %02d $port); then
printf %02d $port
break
fi
done
}
function get_scale {
local localsize=$(xrandr | grep \* | awk '{ print $1 }')
#echo "localsize: $localsize" >&2
local remotesize=$(ssh $REMOTEHOST "export DISPLAY=$REMOTEDISPLAY; xrandr" | grep \* | awk '{ print $1 }')
if [ -z "$remotesize" ]; then
remotesize=$(ssh $REMOTEHOST "export DISPLAY=$REMOTEDISPLAY; xrandr" | grep \+ | awk '{ print $1 }')
fi
if [ -z "$remotesize" ]; then
remotesize=$(ssh $REMOTEHOST "export DISPLAY=$REMOTEDISPLAY; xrandr" | grep current | sed 's/\([0-9]*\) x \([0-9]*\),\{0,1\}/\1x\2/g' | awk '{ print $6 }')
fi
#echo "remotesize: $remotesize" >&2
local localx=$(echo $localsize | sed 's/x.*//')
#echo "localx: $localx" >&2
local localy=$(echo $localsize | sed 's/.*x//')
#echo "localy: $localy" >&2
local adjusty=75 # adjust to account for panels and other decoractions
#echo "adjusty: $adjustx" >&2
localy=$(($localy - $adjusty))
#echo "localy: $localy" >&2
local remotex=$(echo $remotesize | sed 's/x.*//')
#echo "remotex: $remotex" >&2
local remotey=$(echo $remotesize | sed 's/.*x//')
#echo "remotey: $remotey" >&2
local scalex=$(echo $localx $remotex | awk '{ printf "%.2f\n", $1/$2 }')
#echo "scalex: $scalex" >&2
local scaley=$(echo $localy $remotey | awk '{ printf "%.2f\n", $1/$2 }')
#echo "scaley: $scaley" >&2
local scale
if [ $(echo "$scalex <= $scaley" | bc -l) -eq 1 ]; then
scale=$scalex
else
scale=$scaley
fi
#echo "scale: $scale" >&2
echo $scale
}
# TODO: fix race condition here. Instead of searching for an available
# port, We should just try the port starting at 5901 below and increment
# until it works.
LOCAL_DESKTOP=$(find_local_available_desktop)
LOCAL_PORT=59$LOCAL_DESKTOP
SCALE=$(get_scale)
echo "scale: $SCALE" >&2
X11VNC_LOG=$(mktemp --tmpdir x11vnc.tmp.XXXXXXXXXX)
ssh -t -L $LOCAL_PORT:localhost:5900 $REMOTEHOST "x11vnc -localhost -display $REMOTEDISPLAY -timeout 60 -scale $SCALE -dp" > $X11VNC_LOG 2>&1 &
X11VNC_PID=$!
while true; do
DESKTOP=$(grep "The VNC desktop is" $X11VNC_LOG | awk '{ print $5 }')
if [ -n "$DESKTOP" ]; then
rm -f $X11VNC_LOG
break
fi
sleep 0.2
done
#vinagre --vnc-scale localhost:$LOCAL_DESKTOP
vncviewer -quality 4 -encodings "copyrect tight hextile" localhost:$LOCAL_DESKTOP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment