On Zorin OS, GNOME is the default desktop interface and GDM is the default greeter (login screen). It seems that GDM will always attach to :0
which is display 0, thus when I had my x11vnc
service running, it will always work.
But in my new installation, Debian 13 with LightDM, each screen (desktop and login) is attached to different display. If a user is logged in and then he performs a “Lock Screen”, there will be two instances, which causes the current connection to black screen as it’s attached to the desktop screen.
I had to use AI to help me write a script and then perfected by myself which will loop and check for displays. It will always attach to :1
(i.e. login screen) if it’s found first and attach to :0
if there is no :1
.
Below is the snippet used:
#!/bin/bash
# File to store the previous Xorg process state
STATE_FILE="/tmp/x11vnc_xorg_state"
VNC_PASS=/home/jerry/.vnc/passwd
# Function to find the active display and its Xauthority file
find_active_display() {
# Check for lock screen (:1)
if [ -f /var/run/lightdm/root/:1 ]; then
echo ":1"
echo "/var/run/lightdm/root/:1"
# Check for greeter (:0, no user logged in)
elif [ -f /var/run/lightdm/root/:0 ]; then
echo ":0"
echo "/var/run/lightdm/root/:0"
# Check for user session (:0)
elif [ -f /run/user/*/xauth* ]; then
echo ":0"
echo "$(find /run/user -name 'xauth*' -type f | head -n 1)"
else
echo "No Xauthority file found." >&2
return 1
fi
}
# Function to get current Xorg processes
get_xorg_state() {
#ps aux | grep '[X]org' | awk '{print $12 " " $16}' | sort | sha1sum | awk '{print $1}'
ls /var/run/lightdm/root | sha1sum | awk '{print $1}'
}
has_x11vnc_running() {
if ps aux | grep -P "\bx11vnc -display\b" &>/dev/null; then
true
else
false
fi
}
stop_x11vnc() {
pkill -f "x11vnc -display" 2>/dev/null
# Wait for all x11vnc processes to terminate
while pgrep -f "x11vnc -display" >/dev/null; do
sleep 0.1
done
}
start_x11vnc() {
x11vnc -display "$DISPLAY_NUM" -auth guess -rfbauth $VNC_PASS -noxdamage -forever -shared -rfbport 5900 -bg -o /var/log/x11vnc.log &
#x11vnc -display "$DISPLAY_NUM" -auth guess -rfbauth /etc/x11vnc.passwd -noxdamage -forever -shared -rfbport 5900 -bg &
sleep 2
}
# Store initial Xorg state
get_xorg_state > "$STATE_FILE"
# Main loop to monitor Xorg processes
while :; do
# Get current display and Xauthority
read -r DISPLAY_NUM XAUTH < <(find_active_display)
if [ $? -ne 0 ]; then
echo "No display found, retrying in 5 seconds..." >&2
sleep 5
continue
fi
## Start x11vnc in background
if ! has_x11vnc_running; then
start_x11vnc
fi
# Monitor Xorg processes for changes
while :; do
sleep 2
CURRENT_STATE=$(get_xorg_state)
PREV_STATE=$(cat "$STATE_FILE")
if [ "$CURRENT_STATE" != "$PREV_STATE" ]; then
echo "Xorg process change detected, restarting x11vnc..." >&2
stop_x11vnc
echo "$CURRENT_STATE" > "$STATE_FILE"
break
else
break
fi
done
done
UPDATE: This version uses inotifywait
(I really dislike polling methods).
#!/bin/bash
VNC_PASS=/home/jerry/.vnc/passwd
# Function to find the active display and its Xauthority file
find_active_display() {
# Check for lock screen (:1)
if [ -f /var/run/lightdm/root/:1 ]; then
echo ":1"
echo "/var/run/lightdm/root/:1"
# Check for greeter (:0, no user logged in)
elif [ -f /var/run/lightdm/root/:0 ]; then
echo ":0"
echo "/var/run/lightdm/root/:0"
# Check for user session (:0)
elif [ -f /run/user/*/xauth* ]; then
echo ":0"
echo "$(find /run/user -name 'xauth*' -type f | head -n 1)"
else
echo "No Xauthority file found." >&2
return 1
fi
}
has_x11vnc_running() {
if ps aux | grep -P "\bx11vnc -display\b" &>/dev/null; then
true
else
false
fi
}
stop_x11vnc() {
pkill -9 -f "x11vnc -display" 2>/dev/null
# Wait for all x11vnc processes to terminate
while pgrep -f "x11vnc -display" >/dev/null; do
sleep 1
done
}
start_x11vnc() {
# Get current display and Xauthority
read -r DISPLAY_NUM XAUTH < <(find_active_display)
if [ $? -ne 0 ]; then
echo "No display found, retrying in 5 seconds..." >&2
sleep 5
fi
x11vnc -display "$DISPLAY_NUM" -auth guess -rfbauth $VNC_PASS -noxdamage -forever -shared -rfbport 5900 -bg -o /var/log/x11vnc.log &
}
start_x11vnc
inotifywait -m /var/run/lightdm/root -e create -e delete -e modify |
while read -r directory events filename; do
echo "Detected change in $directory: $filename ($events)" >&2
if ! has_x11vnc_running; then
start_x11vnc
else
stop_x11vnc
start_x11vnc
fi
done