Manche VMs lassen sich nicht per SSH oder API konfigurieren – etwa Firewall-Appliances, Router-VMs oder Installer ohne Netzwerk. Hier hilft qm sendkey: simulierte Tastatureingaben direkt an die VM-Konsole.
Grundlagen
# Einzelne Taste senden
qm sendkey <vmid> <key>
# Beispiele
qm sendkey 100 a
qm sendkey 100 kp_enter
qm sendkey 100 ctrl-alt-delete
Der Befehl sendet Tastenanschläge an die VM-Konsole, als würde jemand physisch an der Tastatur tippen.
Verfügbare Tasten
Buchstaben und Zahlen
qm sendkey 100 a # Buchstabe a
qm sendkey 100 5 # Ziffer 5
qm sendkey 100 shift-a # Großbuchstabe A
Sonderzeichen
qm sendkey 100 dot # Punkt (.)
qm sendkey 100 minus # Minus (-)
qm sendkey 100 slash # Slash (/)
qm sendkey 100 shift-2 # @ (auf deutscher Tastatur)
Steuerzeichen
qm sendkey 100 kp_enter # Enter (Keypad)
qm sendkey 100 ret # Return
qm sendkey 100 tab # Tab
qm sendkey 100 esc # Escape
qm sendkey 100 backspace # Backspace
qm sendkey 100 delete # Delete
Tastenkombinationen
qm sendkey 100 ctrl-alt-delete
Praktisches Beispiel: IP-Adresse eingeben
# 192.168.100.1 eingeben
qm sendkey 100 1
qm sendkey 100 9
qm sendkey 100 2
qm sendkey 100 dot
qm sendkey 100 1
qm sendkey 100 6
qm sendkey 100 8
qm sendkey 100 dot
qm sendkey 100 1
qm sendkey 100 0
qm sendkey 100 0
qm sendkey 100 dot
qm sendkey 100 1
qm sendkey 100 kp_enter
Kritische Herausforderungen
1. Timing ist alles
Die VM braucht Zeit zum Verarbeiten. Ohne Pausen können Eingaben verloren gehen:
# FALSCH - zu schnell
qm sendkey 100 r
qm sendkey 100 o
qm sendkey 100 o
qm sendkey 100 t
# RICHTIG - mit Pausen
qm sendkey 100 r
sleep 0.5
qm sendkey 100 o
sleep 0.5
qm sendkey 100 o
sleep 0.5
qm sendkey 100 t
Bei Menüwechseln oder Boot-Vorgängen längere Pausen einbauen:
qm start 100
sleep 30 # Boot-Zeit abwarten
qm sendkey 100 kp_enter
2. Tastatur-Layout beachten
qm sendkey verwendet US-Tastatur-Layout. Deutsche Sonderzeichen sind problematisch:
# @ auf US-Layout
qm sendkey 100 shift-2 # ergibt @
3. Keine Fehlerprüfung möglich
Man sieht nicht, ob die Eingabe ankam oder was auf dem Bildschirm steht:
# Blindflug - Script weiß nicht, ob Eingabe erfolgreich war
qm sendkey 100 r
qm sendkey 100 o
qm sendkey 100 o
qm sendkey 100 t
qm sendkey 100 kp_enter
# Fehler werden nicht erkannt
Workaround: Feste Wartezeiten und deterministisches Verhalten der VM voraussetzen.
4. Mehrstellige Zahlen dynamisch eingeben
Statische Eingaben sind einfach. Dynamische Werte erfordern Logik:
# Zahl in Ziffern zerlegen
send_number() {
local num=$1
local vmid=$2
if [ $num -ge 100 ]; then
# Dreistellig: 123 → 1, 2, 3
local d1=$((num / 100))
local d2=$(((num % 100) / 10))
local d3=$((num % 10))
qm sendkey $vmid $d1
qm sendkey $vmid $d2
qm sendkey $vmid $d3
elif [ $num -ge 10 ]; then
# Zweistellig: 42 → 4, 2
local d1=$((num / 10))
local d2=$((num % 10))
qm sendkey $vmid $d1
qm sendkey $vmid $d2
else
# Einstellig
qm sendkey $vmid $num
fi
}
# Verwendung (100 ist die VM-ID)
send_number 192 100
qm sendkey 100 dot
send_number 168 100
5. Enter vs. Return vs. KP_Enter
Verschiedene VMs reagieren unterschiedlich:
qm sendkey 100 kp_enter # Keypad Enter (meist sicherer)
qm sendkey 100 ret # Return-Taste
qm sendkey 100 enter # Alias für ret
Empfehlung: kp_enter verwenden – funktioniert in den meisten Fällen.
Anwendungsfälle
1. BIOS/UEFI-Konfiguration
# Boot-Reihenfolge ändern
sleep 2
qm sendkey 100 right
qm sendkey 100 down
qm sendkey 100 kp_enter
2. Installer ohne Netzwerk
# Debian-Installer durchklicken
qm sendkey 100 kp_enter # Sprache wählen
sleep 1
qm sendkey 100 kp_enter # Land wählen
sleep 1
qm sendkey 100 kp_enter # Tastatur wählen
3. Firewall-/Router-Konfiguration
# pfSense/OPNsense initial setup
qm sendkey 100 1 # Interface assignment
qm sendkey 100 kp_enter
qm sendkey 100 2 # IP konfigurieren
qm sendkey 100 kp_enter
# IP eingeben...
4. Grub-Menü steuern
# Kernel-Option wählen
qm sendkey 100 down
qm sendkey 100 down
qm sendkey 100 kp_enter
Best Practices
1. Konsistente Wartezeiten
BOOT_WAIT=30
MENU_WAIT=2
INPUT_WAIT=0.5
sleep $BOOT_WAIT
qm sendkey 100 1
sleep $INPUT_WAIT
2. Dry-Run implementieren
send_key() {
local vmid=$1
local key=$2
if [ "$DRY_RUN" = true ]; then
echo "[DRY] qm sendkey $vmid $key"
else
qm sendkey $vmid $key
fi
}
3. Logging
log_keystroke() {
echo "$(date +%H:%M:%S) - VM $1: $2" >> keystroke.log
qm sendkey "$1" "$2"
}
Debugging
Problem: Eingaben kommen nicht an
# Längere Pausen testen
sleep 1 # statt 0.5
Problem: Falsche Zeichen
# Tastatur-Layout in VM prüfen
# US-Layout erzwingen
Problem: VM reagiert nicht
# Konsole manuell öffnen und beobachten
# NoVNC-Console in Proxmox Web-UI
Limitationen
- Keine Rückmeldung über Erfolg/Misserfolg
- Abhängig von exaktem Timing
- Tastatur-Layout-Probleme
- Nicht geeignet für komplexe interaktive Eingaben
- Keine Fehlerbehandlung möglich
Mein Eindruck
qm sendkey ist ein mächtiges Werkzeug für Automation in Fällen, wo SSH/API nicht verfügbar ist. Der Schlüssel zum Erfolg: deterministisches VM-Verhalten, robuste Wartezeiten und gründliches Testing. Nicht elegant, aber effektiv.