→ 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. 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 2. Select the VM number to attach 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) 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.