Automatically Propagate Terminal Window Size to KVM Guest via virsh Console


2 views

When working with KVM virtual machines through virsh console, one common frustration is that terminal window resizing doesn't automatically propagate to the guest OS. While SSH connections handle this gracefully by updating the TTY dimensions, the serial console connection behaves differently.

Applications that rely on terminal dimensions (like vim, tmux, or htop) display incorrectly when the window size changes. The guest OS maintains its initial TTY size until manually updated:

# Check current terminal dimensions
$ stty -a | grep -E "rows|columns"
rows 24; columns 80;

The immediate solution is to manually set the dimensions using stty:

# Set terminal to 40 rows and 120 columns
$ stty rows 40 cols 120

However, this becomes tedious when frequently resizing windows during development sessions.

For Linux guests, we can create a more elegant solution using screen and a small script:

# Install screen if not present
$ sudo apt-get install screen  # Debian/Ubuntu
$ sudo yum install screen      # RHEL/CentOS

# Create ~/.screenrc configuration
termcapinfo xterm* 'ti@:te@'
defshell -bash

Then create a wrapper script for virsh console:

#!/bin/bash
VM_NAME=$1

# Get current terminal dimensions
ROWS=$(stty size | awk '{print $1}')
COLS=$(stty size | awk '{print $2}')

# Connect to VM and set dimensions
virsh console $VM_NAME <<EOF
stty rows $ROWS cols $COLS
screen -r || screen -S main
EOF

For tmux users, add this to your ~/.tmux.conf:

set -g terminal-overrides 'xterm*:smcup@:rmcup@'
set -g update-environment "TERM LINES COLUMNS"

Then launch your session with:

tmux new-session 'virsh console your-vm; bash'

For modern Linux distributions using systemd, create a service to monitor terminal size changes:

# /etc/systemd/system/ttyresize.service
[Unit]
Description=TTY Resize Daemon
After=getty.target

[Service]
Type=simple
ExecStart=/usr/bin/bash -c "while true; do eval $(resize); sleep 1; done"
Restart=always

[Install]
WantedBy=multi-user.target

Enable with:

sudo systemctl enable ttyresize.service
sudo systemctl start ttyresize.service

After implementing any solution, verify it works by:

  1. Connecting to your VM
  2. Checking initial dimensions with stty -a
  3. Resizing your terminal window
  4. Checking dimensions again

When working with KVM virtualization, many administrators use virsh console to access guest VMs through the serial interface. Unlike SSH connections which automatically handle terminal resizing, the serial console connection doesn't propagate window dimension changes to the guest OS.


# SSH connection shows dynamic resizing
$ stty -a | grep rows
rows 40; columns 120

# virsh console shows static dimensions
virsh console myvm
$ stty -a | grep rows
rows 24; columns 80  # Fixed regardless of client window size

The serial console (ttyS0) in Linux guests doesn't implement the SIGWINCH signal handler that modern terminal emulators use for dynamic resizing. This is fundamentally different from pseudo-terminals (ptys) which support this feature.

Here are three approaches to solve this issue:

1. Manual resizing with stty

The quickest workaround is to manually set dimensions after connecting:


# Inside guest VM after virsh console connection
stty rows $(stty -F /dev/tty size | awk '{print $1}')
stty cols $(stty -F /dev/tty size | awk '{print $2}')

2. Automatic resizing with a helper script

Create a client-side script that watches for window changes:


#!/bin/bash
# resize-virsh-console.sh
VM_NAME=$1

watch -n 1 -t "stty -F /dev/tty size | \\
  xargs -I{} virsh qemu-monitor-command $VM_NAME \\
  --hmp \"sendkey up\"  # Simulate keypress to trigger resize"

3. Alternative console access methods

Consider these alternatives that handle resizing better:

  • SPICE protocol with remote-viewer
  • VNC with TigerVNC or TightVNC
  • SSH into guest (requires network configuration)

For frequent users, you can patch the guest kernel to better handle serial console resizing:


# In guest kernel config:
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y

If resizing still doesn't work:

  1. Verify guest has agetty or equivalent running on ttyS0
  2. Check that stty -F /dev/ttyS0 shows correct permissions
  3. Test with different terminal emulators (gnome-terminal, xterm, etc.)