WSL USB Passthrough 與隨身碟自動掛載

我們在 Windows WSL串接 USB-RS422 與 PPP裡面介紹了如何掛載 USB 實體裝置到 WSL,本篇我們要介紹如何自動掛載 USB 隨身碟。由於 WSL Kernel 要重新編譯,如果你的 kernel 沒有重編過,請先參考前文。沒有重編過的 kernel, 會因缺乏 driver,在 WSL 可以看到裝置插入訊息,但不能驅動,不會產生 /dev/sdX。

 

前言

本文示範如何在 Ubuntu 18.04(或其他以 systemd 為 init 的 Linux 發行版)上,實作一套「插入 USB 隨身碟後自動掛載、廣播提示一般使用者可以使用、並提供一般使用者以 sudo 免密碼安全卸載」的完整流程。

規劃

整體設計重點如下:

  1. 使用 udev 偵測 USB mass storage 分割區(例如 /dev/sdd1)。
  2. udev 不直接執行 mount,而是透過觸發一個 systemd 範本服務 usb-mount@.service。以免因namespace不同,而讓一般用戶看不到mount
  3. systemd 服務執行 usb-auto-mount.sh,在「正常的 mount namespace」中掛載隨身碟,並廣播提示所有終端機。
  4. 提供 usb-safe-remove.sh,負責 umount(與選擇性 power-off),再廣播「可以安全拔除」。
  5. 透過 sudoers 設定,讓屬於 usbmount 群組的一般使用者可免密碼執行 usb-safe-remove.sh。

 

相較於直接在 udev 的 RUN+= 中呼叫 mount,這種「udev + systemd」的設計可以避免 systemd-udevd 預設的 PrivateMounts=yes 所帶來的 mount namespace 問題,確保掛載在整個系統中可見。

 

udev + systemd 自動掛載 USB 隨身碟,並以 sudo 免密碼卸載

環境假設與目標

  • 作業系統:Ubuntu 18.04(採用 systemd)
  • USB 裝置:一般 USB 隨身碟 / USB 行動硬碟,經由 usb-storage driver 管理
  • 目標:
    • 插入 USB 隨身碟後,自動掛載到 /usb(或你指定的掛載點)
    • 掛載成功後,對所有登入終端機(tty / pts)顯示提示訊息

一般使用者可用 sudo usb-safe-remove.sh 免密碼安全卸載

 

自動掛載腳本 usb-auto-mount.sh

首先建立主腳本,負責:

  1. 接收裝置節點(例如 /dev/sdd1)
  2. 使用 mount -o sync 掛載裝置
  3. 對所有 tty / pts 廣播掛載成功或失敗訊息

 

建立檔案 /usr/local/sbin/usb-auto-mount.sh:

內容如下:

儲存後,賦予執行權限:

建立 systemd 範本服務 usb-mount@.service

為避免 systemd-udevd 的 PrivateMounts 問題,我們不直接在 udev 內執行 mount,而是透過 systemd 啟動一個 oneshot 服務來呼叫 usb-auto-mount.sh。

檔案 /etc/systemd/system/usb-mount@.service,內容如下:

 

建立完成後,重新載入 systemd 設定:

建立 udev 規則偵測 USB 隨身碟

我們希望只對真正的 USB mass storage 分割區自動掛載,因此 rule 需要過濾:

  • SUBSYSTEM==”block”:只處理 block 裝置
  • KERNEL==”sd[b-z][0-9]”:略過 sda(系統碟),只看 sdb1、sdc1… 等外接磁碟分割區
  • SUBSYSTEMS==”usb”、ENV{ID_BUS}==”usb”、ENV{ID_USB_DRIVER}==”usb-storage”:確定是 USB mass storage
  • ENV{ID_FS_USAGE}==”filesystem”:只處理有檔案系統的分割區
  • 透過 ENV{SYSTEMD_WANTS} 觸發 usb-mount@%k.service

 

建立 /etc/udev/rules.d/99-usb-auto-mount.rules,內容如下:

儲存後,重新載入 udev 設定:

建立安全卸載腳本 usb-safe-remove.sh

掛載完成後,要安全移除隨身碟,必須在實體拔除前執行 umount。以下腳本提供一個簡單的「一鍵安全移除」機制:

建立 /usr/local/sbin/usb-safe-remove.sh,內容如下:

儲存後給予執行權限:

一般使用流程為:

  1. 插入隨身碟 → udev + systemd 自動掛載到 /usb,並廣播「已就緒」。
  2. 使用中可在 /usb 讀寫檔案。
  3. 要拔除時,一般使用者執行 sudo usb-safe-remove.sh。

設定 sudo 免密碼執行安全卸載

為了兼顧便利性與安全性,我們只讓特定群組 usbmount 的成員可以「免密碼 sudo 執行 usb-safe-remove.sh」,而不是把所有 sudo 都設成免密碼。

 

  1. 建立群組 usbmount(若已存在會顯示錯誤,可忽略):
    sudo groupadd usbmount
  2. 將需要操作隨身碟的使用者加入 usbmount 群組(以 user 為例):
    sudo usermod -aG usbmount user

 

  1. 建立 sudoers 設定檔, sudo visudo -f /etc/sudoers.d/usbmount 並輸入:

%usbmount ALL=(root) NOPASSWD: /usr/local/sbin/usb-safe-remove.sh

  1. 完成後,加入 usbmount 群組的使用者就可以 sudo usb-safe-remove.sh 在不輸入密碼的情況下安全卸載 /usb。使用者需重新登入一次,群組才會生效。

 

說明:

– %usbmount:代表 usbmount 群組。
– ALL=(root):允許在任意主機上以 root 身份執行。
– NOPASSWD:執行指定指令時不需要輸入密碼。
– 僅限 /usr/local/sbin/usb-safe-remove.sh 這一支腳本免密碼,其他 sudo 指令仍需密碼。

usbipd 自動掛載

由於在 WSL 中,插拔 USB 裝置/或重開系統後,還需重新 attach,可利用下列 batch file 來進行自動 attach 的動作。

Mount 網路磁碟機

若網路磁碟機未出現在 df 內,可自行在 /mnt 內建立掛載點,在以下列指令執行掛載

結語

透過 udev + systemd + 自訂腳本,我們可以在 Ubuntu 18.04 上建立一套既實用又相對安全的 USB 隨身碟自動掛載與卸載機制:

– udev 負責偵測 USB mass storage 裝置並觸發 systemd 服務。
– systemd 服務在正確的 mount namespace 中執行掛載腳本。
– 掛載與卸載腳本負責實際 mount/umount,以及對所有終端機廣播狀態。
– sudoers 適度放行,使一般使用者能以 sudo 免密碼安全移除裝置,而不暴露整體系統。

 

依照本文步驟完成設定後,你應該就能達成:
「插上 USB → 自動掛載並在所有終端機顯示『可以用了』;
執行 sudo usb-safe-remove.sh → 安全卸載並顯示『可以拔了』」
的完整工作流程。

Leave a Reply(Name請以user_開頭,否則會被判定會垃圾息)

請輸入答案 × 6 = 6