In multi-user Linux systems with multiple X servers running on different virtual terminals (e.g., tty7 and tty8), administrators often need to determine which virtual terminal is currently active (i.e., displayed on the physical monitor). This becomes particularly challenging when accessing the system remotely via SSH.
The traditional w
command shows logged-in users and their associated TTYs, but doesn't indicate which virtual terminal is currently active:
$ w
21:51:30 up ? days, 4:22, ? users, load average: 1.72, 1.68, 1.67
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
u1 pts/0 :0 Sat18 4days 0.00s 11.68s kdeinit4: kded4 [kdeinit]
u2 pts/5 :1 Mon17 2days 0.00s 6.65s kdeinit4: kded4 [kdeinit]
The most reliable method involves querying the kernel's virtual console subsystem:
# Check active VT (virtual terminal)
$ sudo fgconsole
7
# Alternative method using sysfs
$ cat /sys/class/tty/tty0/active
tty7
We can cross-reference this with running X servers:
$ ps aux | grep '/usr/bin/[X]'
root 2944 3.1 12.4 670040 1019904 tty7 Ss+ Aug27 187:52 /usr/bin/X :0 vt7 -br -nolisten tcp -auth /var/run/xauth/A:0-??????
root 5507 0.9 3.7 425136 309676 tty8 Ss+ Aug29 29:38 /usr/bin/X :1 vt8 -br -nolisten tcp -auth /var/run/xauth/A:1-??????
Here's a complete bash solution that combines these approaches:
#!/bin/bash
# Get active VT number
ACTIVE_VT=$(fgconsole 2>/dev/null || cat /sys/class/tty/tty0/active | sed 's/tty//')
# Find corresponding X display
X_DISPLAY=$(ps aux | awk -v vt="$ACTIVE_VT" \
'/\/usr\/bin\/X/ && $7 == "tty"vt { \
for(i=1;i<=NF;i++) { \
if($i ~ /^:[0-9]+$/) {print $i; exit} \
} \
}')
echo "Active VT: tty${ACTIVE_VT}"
echo "Corresponding X display: ${X_DISPLAY:-Not found}"
On systems with systemd, we can query logind:
$ busctl get-property org.freedesktop.login1 /org/freedesktop/login1/seat/self org.freedesktop.login1.Seat ActiveSession
o "/org/freedesktop/login1/session/c2"
$ busctl get-property org.freedesktop.login1 /org/freedesktop/login1/session/c2 org.freedesktop.login1.Session VTNr
u 7
These methods may have limitations with:
- Wayland sessions
- Nested X servers
- Some GPU drivers that handle VT switching differently
- Systems without proper permissions for the SSH user
When working with a multi-user Linux system (in this case Debian 6.0 with ATI graphics), you might encounter a situation where multiple X sessions are running on different virtual terminals (e.g., tty7 and tty8), but only one is actively displayed on the physical monitor. The challenge arises when you need to remotely determine which X display is currently active through an SSH connection.
For system administrators and developers working remotely, knowing the active VT is crucial for:
- Debugging graphical sessions
- Managing user sessions
- Automating display-related tasks
- Implementing display-switching scripts
The standard w
command shows logged-in users but doesn't indicate the active VT:
$ w
21:51:30 up ? days, 4:22, ? users, load average: 1.72, 1.68, 1.67
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
u1 pts/0 :0 Sat18 4days 0.00s 11.68s kdeinit4: kded4 [kdeinit]
u2 pts/5 :1 Mon17 2days 0.00s 6.65s kdeinit4: kded4 [kdeinit]
Similarly, checking X processes doesn't reveal which is active:
$ ps aux|grep /usr/bin/[X]
root 2944 3.1 12.4 670040 1019904 tty7 Ss+ Aug27 187:52 /usr/bin/X :0 vt7 -br -nolisten tcp -auth /var/run/xauth/A:0-??????
root 5507 0.9 3.7 425136 309676 tty8 Ss+ Aug29 29:38 /usr/bin/X :1 vt8 -br -nolisten tcp -auth /var/run/xauth/A:1-??????
The most reliable method is to examine the virtual console (vc) subsystem:
$ cat /sys/class/tty/tty0/active
tty7
This file contains the currently active virtual terminal. For a more robust solution, you can use this bash function:
get_active_vt() {
local active_vt
if [[ -e /sys/class/tty/tty0/active ]]; then
active_vt=$(cat /sys/class/tty/tty0/active)
echo "Active VT: ${active_vt}"
else
echo "Could not determine active VT" >&2
return 1
fi
}
To find which X display corresponds to the active VT:
find_active_x_display() {
local active_vt x_pid x_display
active_vt=$(cat /sys/class/tty/tty0/active)
x_pid=$(pgrep -f "X.*vt${active_vt#tty}")
if [[ -n "$x_pid" ]]; then
x_display=$(ps -p "$x_pid" -o cmd= | grep -oP ':[0-9]+')
echo "Active X display: $x_display"
else
echo "No X server running on $active_vt" >&2
return 1
fi
}
For systems without the sysfs interface, you can try:
$ fgconsole
7
Or query the kernel directly:
$ sudo cat /dev/vcs | head -1
Note that:
- Some systems use Wayland instead of X
- Virtual terminal behavior may vary between distributions
- Permissions might be required to access certain files
Here's a complete script to monitor active VT changes:
#!/bin/bash
previous_vt=""
while true; do
current_vt=$(cat /sys/class/tty/tty0/active 2>/dev/null)
if [[ "$current_vt" != "$previous_vt" ]]; then
echo "[$(date)] VT changed to $current_vt"
previous_vt="$current_vt"
fi
sleep 1
done