Troubleshooting Virsh VM Console: Why No Output Appears and How to Fix Serial PTY Configuration


2 views

When working with KVM/QEMU virtual machines managed through libvirt's virsh, a common frustration occurs when the VM console shows no output despite proper configuration. Let's analyze the key symptoms from the case:


  
  
  


  
  
  

The lsof output reveals the critical difference between working and non-working cases:

# Working VM (direct kvm launch)
kvm       25093         root    0u      CHR              136,3         0t0          6 /dev/pts/3
kvm       25093         root    1u      CHR              136,3         0t0          6 /dev/pts/3
kvm       25093         root    2u      CHR              136,3         0t0          6 /dev/pts/3

# Non-working VM (virsh launch)
kvm        8341 libvirt-qemu    0r      CHR                1,3         0t0       4640 /dev/null
kvm        8341 libvirt-qemu    4u      CHR                5,2         0t0       4897 /dev/ptmx

To prevent libvirt from redirecting stdio to /dev/null, modify your domain XML configuration:

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  ...
  <devices>
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target type='serial' port='0'/>
    </console>
  </devices>
  <qemu:commandline>
    <qemu:arg value='-serial'/>
    <qemu:arg value='stdio'/>
  </qemu:commandline>
</domain>

Ensure your VM's boot configuration includes proper serial console parameters. The example shows correct configuration:

kernel /boot/vmlinuz-2.6.24-28-virtual root=UUID=7a1685b9-ecc8-4b70-932c-459a6faac07d ro quiet splash console=tty0 console=ttyS0,9600n8

If the issue persists, try these alternative connection methods:

# Method 1: Using screen
screen /dev/pts/6

# Method 2: Direct socat connection
socat - /dev/pts/6,rawer

# Method 3: Using virsh with force option
virsh console --force VM1

To see exactly how libvirt launches QEMU, check the generated command:

ps aux | grep qemu
cat /var/log/libvirt/qemu/VM1.log

Key parameters to verify include:

  • -chardev pty,id=serial0
  • -device isa-serial,chardev=serial0
  • -monitor stdio (missing in problematic case)

Check these common permission-related issues:

# Check libvirt qemu user permissions
ls -la /dev/pts/6

# Check SELinux context
ls -Z /dev/pts/6

# Temporarily test with SELinux in permissive mode
setenforce 0
virsh start VM1
setenforce 1

When attempting to connect to a KVM virtual machine using virsh console, you might encounter a blank screen despite the VM being in running state. This typically indicates a serial console configuration mismatch between the host and guest environments.


# Verify guest XML configuration
virsh dumpxml VM1 | grep -A5 -B5 'console\|serial'

# Check running processes
ps aux | grep kvm.*VM1

The problem often stems from three potential issues:

  1. Missing or incorrect GRUB configuration for serial console
  2. Improper file descriptor redirection in libvirt
  3. PTY allocation conflicts

For the guest VM, ensure your GRUB configuration includes proper serial console parameters:


# Example working GRUB line
GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200n8"

Additionally, check these files in the guest:


/etc/default/grub
/boot/grub/grub.cfg

The serial console configuration in your domain XML should resemble:


<serial type='pty'>
  <source path='/dev/pts/X'/>
  <target port='0'/>
</serial>
<console type='pty' tty='/dev/pts/X'>
  <source path='/dev/pts/X'/>
  <target type='serial' port='0'/>
</console>

For the FD redirection issue shown in your lsof output, modify your libvirt configuration:


# Create or edit /etc/libvirt/qemu.conf
stdio_handler = "file"

Then restart libvirt:


systemctl restart libvirtd

When troubleshooting, try these diagnostic commands:


# Check console connections
virsh ttyconsole VM1

# Verify serial devices
ls -l /dev/pts/ | grep libvirt

# Test raw console output
screen /dev/pts/X 115200

Here's a complete working domain XML snippet for reference:


<devices>
  <serial type='pty'>
    <source path='/dev/pts/2'/>
    <target port='0'/>
  </serial>
  <console type='pty' tty='/dev/pts/2'>
    <source path='/dev/pts/2'/>
    <target type='serial' port='0'/>
  </console>
</devices>