找回密码
 加入我们
搜索
      
查看: 2344|回复: 6

[NAS] PVE如何优雅地实现硬盘柜随需开机,用完下线

[复制链接]
发表于 2024-11-28 13:26 | 显示全部楼层 |阅读模式
本帖最后由 chip_discovery 于 2024-11-28 13:28 编辑

目前在PVE上其他功能算是基本上都实现了,但是就一个功能比较困难:

外接的硬盘柜是USB的,本身对它的定位就是备份和存冷数据,也不用一直在线,徒增功耗且万一局域网被破解那就一锅端。

现状是:
           1.按需开机用智能插座手动通电
           2.直通给虚拟机win,上线后可以读写其中的文件
           3.用完关机就不太方便了,弹出USB柜后,实际上只是相当于设备管理权还给了PVE,因此设备还在线,直接插座断电的话应该会不安全次数+1好像,长期来看也不是办法,但是也不能每次都是去手动插拔USB,太麻烦了

家里已经好几台主机了,再弄一个win 物理机专门管这个硬盘柜也不合适

之前在用群晖的时候倒是操作逻辑整体和win差不多,所以在PVE上有什么办法能“优雅”实现对USB硬盘柜的随用随开,用完弹出USB,硬盘自动下线,然后就可以关智能插座呢?
发表于 2024-11-28 13:34 来自手机 | 显示全部楼层
太难了
我也在等完美解决的办法

不过给这个机器扔柜子里24小时待机眼不见心不烦就完事了  
发表于 2024-11-28 14:12 | 显示全部楼层
物理开关搞一个,做插拔的动作,远程控制,应该是可以做到的吧
发表于 2024-11-28 23:47 来自手机 | 显示全部楼层
看硬盘柜用的什么方案,USB HUB的话可以试下uhubctl https://github.com/mvp/uhubctl
我用在给冷备硬盘盒自动开关电源上,简单好用
 楼主| 发表于 2024-11-29 08:43 | 显示全部楼层
本帖最后由 chip_discovery 于 2024-11-29 09:03 编辑
Aapejiang 发表于 2024-11-28 23:47
看硬盘柜用的什么方案,USB HUB的话可以试下uhubctl https://github.com/mvp/uhubctl
我用在给冷备硬盘盒自 ...


这个项目牛啊,不过好像没看到我那个的型号,VID:PID 那列好像没找到,我那个是152d开头的。
toolfree 贺禧的机架式硬盘柜,有USB和esata两个接口。
我昨天晚上后来想了个办法,让chat*g*p*t写了个脚本,大致思路就是检测到虚拟机102关机后就判断是否还有USB的硬盘,有的话就给他power off
 楼主| 发表于 2024-11-29 09:02 | 显示全部楼层
找chatg*p*t 写的代码,亲测四个硬盘,只要第一个power off,后面三个也自动下线了
本人非程序员,不是很懂代码,如有错误望大佬不吝赐教
  1. #!/bin/bash

  2. # 虚拟机编号
  3. VM_ID=102
  4. # 轮询间隔时间(秒)
  5. POLL_INTERVAL=60
  6. # 最大轮询次数
  7. MAX_RETRIES=10

  8. # 检查虚拟机是否已关机
  9. check_vm_status() {
  10.     local vm_id=$1
  11.     local status=$(qm status "$vm_id" | awk '{print $2}')
  12.     if [[ "$status" == "stopped" ]]; then
  13.         return 0
  14.     else
  15.         return 1
  16.     fi
  17. }

  18. # 动态筛选 USB 类型的硬盘设备
  19. get_usb_devices() {
  20.     lsblk -o NAME,TRAN | grep -i "usb" | awk '{print $1}'
  21. }

  22. # 安全断开 USB 设备
  23. safely_remove_usb() {
  24.     local device=$1

  25.     # 检查设备是否存在
  26.     if [[ ! -e /dev/$device ]]; then
  27.         echo "Device /dev/$device not found. Skipping."
  28.         return
  29.     fi

  30.     # 检查是否安装了 udisksctl
  31.     if command -v udisksctl >/dev/null 2>&1; then
  32.         echo "Using udisksctl to safely remove /dev/$device..."
  33.         
  34.         # 卸载设备的所有分区
  35.         for part in $(lsblk -ln -o NAME /dev/$device); do
  36.             if mount | grep -q "/dev/$part"; then
  37.                 udisksctl unmount -b /dev/$part 2>/dev/null
  38.                 echo "Unmounted /dev/$part"
  39.             fi
  40.         done

  41.         # 关闭设备电源
  42.         udisksctl power-off -b /dev/$device
  43.         echo "Device /dev/$device powered off."
  44.     else
  45.         echo "udisksctl not found. Falling back to /sys method for /dev/$device..."
  46.         
  47.         # 卸载设备的所有分区
  48.         for part in $(lsblk -ln -o NAME /dev/$device); do
  49.             if mount | grep -q "/dev/$part"; then
  50.                 umount /dev/$part 2>/dev/null
  51.                 echo "Unmounted /dev/$part"
  52.             fi
  53.         done

  54.         # 从系统中移除设备
  55.         echo 1 > /sys/block/$device/device/delete
  56.         echo "Device /dev/$device removed from system."
  57.     fi
  58. }

  59. # 主逻辑
  60. main() {
  61.     local retries=0

  62.     while true; do
  63.         if (( retries >= MAX_RETRIES )); then
  64.             echo "Maximum retries reached. Exiting."
  65.             exit 1
  66.         fi

  67.         # 检查虚拟机状态
  68.         if check_vm_status "$VM_ID"; then
  69.             echo "VM $VM_ID is offline. Proceeding with USB device removal."

  70.             # 动态获取所有 USB 类型硬盘设备
  71.             local usb_devices=$(get_usb_devices)
  72.             
  73.             if [[ -z "$usb_devices" ]]; then
  74.                 echo "No USB devices found. Exiting."
  75.                 break
  76.             fi

  77.             # 安全断开所有筛选出的 USB 设备
  78.             for device in $usb_devices; do
  79.                 safely_remove_usb "$device"
  80.             done

  81.             echo "All USB devices have been safely removed."
  82.             break
  83.         else
  84.             echo "VM $VM_ID is still running. Retrying in $POLL_INTERVAL seconds..."
  85.         fi

  86.         retries=$((retries + 1))
  87.         sleep "$POLL_INTERVAL"
  88.     done
  89. }

  90. main
复制代码
发表于 2025-4-24 14:06 | 显示全部楼层
有点意思
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

Archiver|手机版|小黑屋|Chiphell ( 沪ICP备12027953号-5 )沪公网备310112100042806 上海市互联网违法与不良信息举报中心

GMT+8, 2025-4-25 20:48 , Processed in 0.009966 second(s), 5 queries , Gzip On, Redis On.

Powered by Discuz! X3.5 Licensed

© 2007-2024 Chiphell.com All rights reserved.

快速回复 返回顶部 返回列表