→ Applies to: Hyperion 9.x and above
Step 1. Connect to Hyperion appliance via SSH as admin
ssh admin@<your_ip_address_or_hostname>
Step 2. Become Super User
sudo su -
Step 3. Download the script in tmp directory
wget -P /tmp https://storage.googleapis.com/syneto_public_files/downloads/Syneto-Tools/USB/syneto-usbctl.sh
Step 4 (optional). If download fails, manually create and edit /tmp/syneto-usbctl.sh file
vi /tmp/syneto-usbctl.shIMPORTANT
Make sure to copy and paste the exact lines below.#!/bin/bash set -euo pipefail if ! command -v lsusb &>/dev/null; then echo "Missing lsusb. Install with: sudo dnf install usbutils" exit 1 fi if ! command -v virsh &>/dev/null; then echo "Missing virsh. Install libvirt." exit 1 fi ############################################################ # Select VM (ALL states) ############################################################ select_vm() { echo echo "=== ALL VMs ===" mapfile -t VM_LIST < <(virsh list --all --name | sed '/^$/d') if [[ ${#VM_LIST[@]} -eq 0 ]]; then echo "No VMs found." exit 1 fi for i in "${!VM_LIST[@]}"; do state=$(virsh domstate "${VM_LIST[$i]}") printf "%2d) %-25s [%s]\n" "$((i+1))" "${VM_LIST[$i]}" "$state" done echo read -p "Select VM number: " n (( n>=1 && n<=${#VM_LIST[@]} )) || { echo "Invalid VM."; exit 1; } VM="${VM_LIST[$((n-1))]}" VM_STATE=$(virsh domstate "$VM") echo "Selected VM: $VM ($VM_STATE)" } ############################################################ # Determine attach mode based on VM state ############################################################ attach_mode() { if [[ "$VM_STATE" == "running" ]]; then ATTACH_OPTS=(--live --persistent) else ATTACH_OPTS=(--persistent) echo "⚠VM is NOT running. USB will be attached persistently only." fi } ############################################################ # ATTACH USB DEVICE ############################################################ attach_usb() { echo echo "=== USB DEVICES ON HOST ===" mapfile -t USB_LIST < <(lsusb) for i in "${!USB_LIST[@]}"; do printf "%2d) %s\n" "$((i+1))" "${USB_LIST[$i]}" done echo read -p "Select USB device number to ATTACH: " n (( n>=1 && n<=${#USB_LIST[@]} )) || { echo "Invalid selection."; exit 1; } line="${USB_LIST[$((n-1))]}" VID=$(echo "$line" | grep -oP "(?<=ID )[\da-fA-F]+(?=:)") PID=$(echo "$line" | grep -oP "(?<=:)[\da-fA-F]+(?= )") if [[ -z "$VID" || -z "$PID" ]]; then echo "⌠Could not parse VID:PID from:" echo " $line" exit 1 fi echo "Detected VID:PID → $VID:$PID" select_vm attach_mode echo echo "Attaching USB device $VID:$PID to $VM ..." virsh attach-device "$VM" "${ATTACH_OPTS[@]}" --file /dev/stdin <<EOF <hostdev mode='subsystem' type='usb' managed='yes'> <source> <vendor id='0x$VID'/> <product id='0x$PID'/> </source> </hostdev> EOF echo "✔ Attached successfully." } ############################################################ # DETACH USB DEVICE (EXACT PERSIST XML MATCHING) ############################################################ detach_usb() { select_vm echo echo "=== ATTACHED USB DEVICES ===" # Extract EXACT persistent XML blocks (no reconstruction) mapfile -d '' -t HOSTDEVS < <( virsh dumpxml --inactive "$VM" | awk ' /<hostdev/ { inblock=1; block=$0; next; } inblock { block = block "\n" $0; if ($0 ~ /<\/hostdev>/) { print block; printf "%c", 0; # NUL terminator for mapfile inblock=0; block=""; } } ' ) if [[ ${#HOSTDEVS[@]} -eq 0 ]]; then echo "No hostdev devices attached in persistent XML." return fi # List devices for i in "${!HOSTDEVS[@]}"; do block="${HOSTDEVS[$i]}" VID=$(echo "$block" | sed -n "s/.*<vendor id='0x\([0-9a-fA-F]*\)'.*/\1/p") PID=$(echo "$block" | sed -n "s/.*<product id='0x\([0-9a-fA-F]*\)'.*/\1/p") echo "$((i+1))) USB Device ${VID:-unknown}:${PID:-unknown}" done echo read -p "Select hostdev number to DETACH: " n (( n>=1 && n<=${#HOSTDEVS[@]} )) || { echo "Invalid selection!"; exit 1; } REAL_XML="${HOSTDEVS[$((n-1))]}" echo echo "Detaching exact persistent XML block:" echo "--------------------------------" echo "$REAL_XML" echo "--------------------------------" # Detach persistent first (must succeed for attach symmetry) printf '%s\n' "$REAL_XML" | virsh detach-device "$VM" --persistent --file /dev/stdin || true # Detach live if VM is running if [[ "$VM_STATE" == "running" ]]; then printf '%s\n' "$REAL_XML" | virsh detach-device "$VM" --live --file /dev/stdin 2>/dev/null || true fi echo "✔ Detach operation completed." } ############################################################ # MAIN MENU ############################################################ echo "===========================================" echo " Syneto USB Management Tool" echo "===========================================" echo "1) Attach USB device to VM" echo "2) Detach USB device from VM" echo "3) Exit" echo "===========================================" read -p "Select option: " choice case "$choice" in 1) attach_usb ;; 2) detach_usb ;; 3) echo "Bye."; exit 0 ;; *) echo "Invalid option"; exit 1 ;; esacSave and EXIT
:wq
Step 5. Give permissions to /tmp/syneto-usbctl.sh file
chmod +x /tmp/syneto-usbctl.sh
Step 6. Run the script
/tmp/syneto-usbctl.shEXAMPLE OUTPUT
=========================================== Syneto USB Management Tool =========================================== 1) Attach USB device to VM 2) Detach USB device from VM 3) Exit =========================================== Select option:
Step 7 (optional). Check that no errors occur
If you receive this error:
--2025-12-03 16:56:25-- https://storage.googleapis.com/syneto_public_files/downloads/Syneto-Tools/USB/syneto-usbctl.sh
Resolving storage.googleapis.com (storage.googleapis.com)... 142.251.208.123, 142.251.39.27, 142.251.38.219, ...
Connecting to storage.googleapis.com (storage.googleapis.com)|142.251.208.123|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5370 (5.2K) [text/x-sh]
Saving to: ‘syneto-usbctl.sh.1’
syneto-usbctl.sh.1 100%[==============================================================================================================================================>] 5.24K --.-KB/s in 0s
2025-12-03 16:56:25 (205 MB/s) - ‘syneto-usbctl.sh.1’ saved [5370/5370]
Missing lsusb. Install with: sudo dnf install usbutils
Install the usbutils package:
sudo dnf install usbutilsEXAMPLE
[root@syneto-os-f0330a82 admin]# sudo dnf install usbutils syneto 4.4 MB/s | 2.1 MB 00:00 Last metadata expiration check: 0:00:01 ago on Wed Dec 3 17:03:17 2025. Dependencies resolved. ===================================================================================================================================================================================================================================================== Package Architecture Version Repository Size ===================================================================================================================================================================================================================================================== Installing: usbutils x86_64 017-1.el9 syneto 115 k Transaction Summary ===================================================================================================================================================================================================================================================== Install 1 Package Total download size: 115 k Installed size: 382 k Is this ok [y/N]: yPress “y” to install the usbutils package
Step 8 (optional). In case of error occurred at Step 7, run the script again
/tmp/syneto-usbctl.shEXAMPLE OUTPUT
=========================================== Syneto USB Management Tool =========================================== 1) Attach USB device to VM 2) Detach USB device from VM 3) Exit =========================================== Select option:
Attach USB device to VM
Step 1. Power off the VM on which to attach the USB device
Step 2. Select the number of the USB device to attach
EXAMPLE
Select option: 1 === USB DEVICES ON HOST === 1) Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub 2) Bus 001 Device 002: ID 1604:10c0 Tascam Dell Integrated Hub 3) Bus 001 Device 003: ID 1da0:55a7 Parade Technologies, Inc. USB2.0 Hub 4) Bus 001 Device 004: ID 0463:ffff MGE UPS Systems UPS 5) Bus 001 Device 005: ID 1604:10c0 Tascam Dell Integrated Hub 6) Bus 001 Device 006: ID 1604:10c0 Tascam Dell Integrated Hub 7) Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub 8) Bus 002 Device 002: ID 1da0:5507 Parade Technologies, Inc. USB3.0 Hub 9) Bus 002 Device 003: ID 0951:1666 Kingston Technology DataTraveler 100 G3/G4/SE9 G2/50 Kyson Select USB device number to ATTACH:
Step 3. Select the VM number to attach the USB device
EXAMPLE
=== ALL VMs === 1) Win2025T2 [shut off] 2) REC-TEST1 [shut off] 3) TEST2 [shut off] 4) ups-monitor [shut off] 5) Win2025T1 [shut off] Select VM number: 1Selected VM: Win2025T2 (shut off) Attaching USB device 0951:1666 to Win2025T2 ... Device attached successfully ✔ Attached successfully.
Detach USB device from VM
Step 1. Select the number of the USB device to detach
EXAMPLE
Select option: 1 === USB DEVICES ON HOST === 1) Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub 2) Bus 001 Device 002: ID 1604:10c0 Tascam Dell Integrated Hub 3) Bus 001 Device 003: ID 1da0:55a7 Parade Technologies, Inc. USB2.0 Hub 4) Bus 001 Device 004: ID 0463:ffff MGE UPS Systems UPS 5) Bus 001 Device 005: ID 1604:10c0 Tascam Dell Integrated Hub 6) Bus 001 Device 006: ID 1604:10c0 Tascam Dell Integrated Hub 7) Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub 8) Bus 002 Device 002: ID 1da0:5507 Parade Technologies, Inc. USB3.0 Hub 9) Bus 002 Device 003: ID 0951:1666 Kingston Technology DataTraveler 100 G3/G4/SE9 G2/50 Kyson Select USB device number to DETACH:
Step 2. Select the VM number to detach the USB device
EXAMPLE
=== ALL VMs === 1) Win2025T2 [running] 2) REC-TEST1 [shut off] 3) TEST2 [shut off] 4) ups-monitor [shut off] 5) Win2025T1 [shut off] Select VM number: 1Selected VM: Win2025T2 (running) Detaching USB device 0951:1666 from Win2025T2 ... Device detached successfully ✔ Detached successfully.