跳到正文

Wiki

其他操作

約 54 分鐘閱讀

本文由簡體中文內容確定性轉換,並受版本化術語表保護。

1.工控機如何連wifi

1.1.現在無法進入ssh

當我們工控機從一個環境移動到另一個環境,且新的環境的wifi我們沒有連線過,我們沒有螢幕如何讓工控機連上網呢?

進入工控機的硬碟目錄,進入/etc/netplan/,底下有很多yaml,找到一個最符合下方格式的yaml:

network: 
  version: 2 
  wifis: 
    NM-6f414fe0-2658-48ff-89ee-c7981b87bc96: 
      renderer: NetworkManager 
      match: 
        name: "wlan0" 
      dhcp4: true 
      dhcp6: true 
      access-points: 
        "EMIS_Vinci_Robocon_5G": 
          auth: 
            key-management: "psk" 
            password: "vinci666" 
          networkmanager: 
            uuid: "6f414fe0-2658-48ff-89ee-c7981b87bc96" 
            name: "EMIS_Vinci_Robocon_5G" 
            passthrough: 
              wifi-security.auth-alg: "open" 
              ipv6.addr-gen-mode: "default" 
              ipv6.ip6-privacy: "-1" 
              proxy._: "" 
      networkmanager: 
        uuid: "6f414fe0-2658-48ff-89ee-c7981b87bc96" 
        name: "EMIS_Vinci_Robocon_5G"

將其改為新wifi的名和密碼:

network:
  version: 2
  wifis:
    wlan0:
      dhcp4: true
      dhcp6: true
      access-points:
        "EMIS_Vinci_Robocon_5G":
          password: "vinci666"

工控機開機即可連上網。

1.2.現在可以ssh

查網絡卡:

nmcli device status

當前連線的Wifi:

nmcli device wifi list

查詢當前周圍有什麼wifi

sudo nmcli device wifi list --rescan yes

連線wifi:

sudo nmcli --ask device wifi connect "新的WiFi名称"

2.SSH遠端開發

2.1.環境準備

1.硬體準備

首先要有一臺工控機(X86小型電腦,專業工控機,樹莓派等等)。

控制系統的硬體載體是具有多樣性的,常用的多是基於ARM、x86等架構的處理器,比如:PC、工控機、樹莓派、NVIDIA Jetson...。不同的處理器都存在一定的優缺點,PC和工控機,處理器效能強大,但是功耗高、體積大、靈活性差,嵌入式系統則反之。對於我們而言,可以根據機器人平臺的電氣、載重、空間以及用途等諸多要素自主選擇合適的控制系統。

無論選用何種處理器,只要是要進行機器人的開發,安裝了ROS或者ROS2,那麼對於開發人員而言,在使用上,沒有任何本質的區別,或者換言之,作為軟體工程師,部分場景下無需關注於硬體的選型。

2.設定固定IP

遠端連線時,不管使用何種工具,需要根據IP地址定位到被連線的主機,再通過賬號和密碼登入該主機,因此,我們需要先獲取該IP地址。並且每次連線時,都需要使用到IP,為了保證連線的便利性和穩定性,最好將被連線主機的IP地址設定為固定IP,具體操作如下。

1.進入設定介面

啟動被連線的主機(啟動時需要連線顯示器或使用HDMI採集卡,並且配置完SSH遠端訪問之後,可以不再使用顯示器或HDMI採集卡),並進入設定介面。

2.配置所連線的網路

3.設定固定IP

檢視當前IP地址。

設定固定IP。

至此,IP配置完畢。

2.2.環境搭建

概念

SSH(Secure Shell)是一種通用的、功能強大的、基於軟體的網路安全解決方案。計算機每次向網路傳送資料時,SSH都會自動對其進行加密。資料到達目的地時,SSH自動對加密資料進行解密。整個過程都是透明的,使用OpenSSH工具將會增進你的系統安全性。SSH安裝容易、使用簡單。

實現

SSH實現架構上分為客戶端和伺服器端兩大部分,客戶端是資料的傳送方,服務端是資料的接收方,當前場景下,我們需要從本地主機發送資料到遠端主機,那麼本地主機需要安裝並啟動SSH客戶端,而遠端主機則需要安裝並啟動SSH服務端,整個實現具體流程如下:

  1. 本地主機安裝SSH客戶端,遠端主機安裝SSH服務端;

  2. 遠端主機啟動SSH服務;

  3. 本地主機登陸遠端主機;

  4. 實現資料傳輸。

1.安裝SSH客戶端與服務端

預設情況下,Ubuntu系統已經安裝了SSH客戶端,因此只需要在遠端主機安裝SSH服務端即可,安裝命令如下:

 sudo apt install openssh-server

如果SSH客戶端需要自行安裝,那麼呼叫如下命令:

sudo apt install openssh-client

2.遠端主機啟動SSH服務

遠端主機啟動 ssh 服務命令如下:

sudo /etc/init.d/ssh start

啟動後可使用如下命令檢視服務是否正常執行:

ps -e | grep ssh

如果啟動成功,會包含 sshd 程式。

以後需要頻繁的使用ssh遠端登入,為了簡化實現,可以將遠端主機的ssh服務設定為開機自啟動,命令如下:

sudo systemctl enable ssh

3.本地遠端登入

登入遠端主機可以呼叫如下命令:

ssh -X 用户名@ip地址

然後根據提示,錄入登陸密碼,即可成功登入。

如果退出,可以呼叫exit命令:

exit

4.實現資料傳輸

通過SSH在本地主機只需呼叫相關指令,便可方便的實現與遠端主機的資料上傳或下載,指令格式如下所示:

上傳檔案指令格式如下:

scp 本地文件路径 账号@ip:路径

上傳資料夾指令格式如下:

scp -r 本地文件夹路径 账号@ip:路径

下載檔案指令格式如下:

scp 账号@ip:路径 本地文件夹路径

下載資料夾指令格式如下:

scp -r 账号@ip:路径 本地文件夹路径

最佳化

每次遠端登入時,都需要輸入密碼,使用不方便,可以藉助金鑰簡化登入過程,實現免密登入,提高操作效率。實現思想是:生成一對公鑰私鑰,私鑰儲存在本地,公鑰上傳至伺服器,每次登入時,本地直接上傳私鑰到伺服器,伺服器有匹配的公鑰就認為是合法使用者,直接建立SSH連線即可。具體實現步驟只有兩步:

  1. 本地生成金鑰對;

  2. 將公鑰上傳至遠端主機。

1.生成金鑰對

本地客戶端生成公私鑰:(一路回車預設即可)

ssh-keygen

上面這個命令會在使用者目錄.ssh資料夾下建立公私鑰:

  1. id_rsa (私鑰);

  2. id_rsa.pub (公鑰)。

2.公鑰上傳

上傳指令如下:

ssh-copy-id -i ~/.ssh/id_rsa.pub 账号@ip

上面這條指令是將本地公鑰上傳到遠端主機的ssh目錄下,該目錄下有檔案authorized_keys儲存了公鑰內容。

以後再遠端登入就無需錄入密碼了。

2.3.使用VScode最佳化

上一節,我們介紹了ssh遠端連線的使用,但是如果只是純粹使用ssh也存在一些不足,比如:編輯檔案內容時,需要使用vi編輯器,且在一個終端內,無法同時編輯多個檔案。本節將介紹一更為實用的功能——VSCode結合外掛實現遠端開發,這使我們可以以圖形化的方式實現遠端開發,比ssh的使用更方便快捷,可以大大的提高程式開發效率。

1.準備工作

VScode遠端開發依賴於ssh,請首先按照上一節內容配置ssh遠端連線。

2.為VScode安裝遠端開發外掛

啟動VScode,首先點選側邊欄的擴充套件按鈕,然後在扩展:商店的搜尋欄輸入Remote Development並點選同名外掛,最後在右側顯示區中點選安装。

3.配置遠端連線

步驟1:使用快捷鍵ctrl + shift + p開啟命令輸入視窗,並輸入Remote-SSH:Connect to Host...,彈出列表中選擇與之同名的選項。

步驟2:步驟1完成將彈出一個新的命令視窗如下,選擇下拉式清單中的 Add New SSH Host。

步驟3:步驟2完成又將彈出一個新的命令視窗,在其中輸入:ssh -X ubuntu@192.168.43.164,其中,ubuntu需要替換為你的登入使用者名稱,192.18.43.164 則替換為被遠端連線主機的ip地址。

步驟4:選擇步驟3完成後的彈窗列表中的第一個選項(或直接回車),即可完成配置,配置成功後會有提示資訊。

4.使用

步驟1:繼續使用快捷鍵ctrl + shift + p開啟命令輸入視窗,並輸入Remote-SSH:Connect to Host...,此時列表中將顯示步驟3中配置的ip地址,直接選擇,選擇後,VScode將開啟一個新的視窗。

或者,也可以點選側邊欄的远程资源管理器,在彈出的伺服器列表中選擇要連線的伺服器,並右擊,選擇在本視窗或新視窗中實現遠端連線。

步驟2:選擇選單欄的文件下的打开文件夹,在彈窗列表中選擇需要開啟的資料夾並點選確定即可。

最終,我們就可以像操作本地檔案一樣實現遠端開發了。

2.4.進階

2.4.1.使用hostname進行ssh

當一個裝置他的IP一直變化,可以用hostname來進行連線。

可以先看你要遠端開發的裝置的hostname是什麼?

hostname

比如輸出的hostname是Dell-G15-5511

那麼在這個裝置上裝上avahi-daemon:

sudo apt install avahi-daemon
sudo systemctl enable --now avahi-daemon

然後你就可以在同區域網的電腦上嘗試:

ping Dell-G15-5511.local

如果能夠ping通就可以了。

那麼以後ssh就可以

ssh 用户名@Dell-G15-5511.local

3.遠端桌面

因為用X11轉發效率太低太低,所以還是要選用遠端訪問桌面的形式來看Rviz2和Gazebo等等(如果有需求的話)

我們選擇使用VNC來看。

  1. 安裝VNC伺服器:

這裡以TigerVNC為例進行安裝:

sudo apt install tigervnc-standalone-server tigervnc-common
  1. 設定VNC密碼:

為VNC使用者設定密碼,執行以下命令:

vncpasswd
  1. 配置VNC啟動指令碼:

建立VNC配置檔案,在使用者家目錄內的.vnc資料夾中建立啟動檔案:

mkdir -p ~/.vnc
nano ~/.vnc/xstartup

在開啟的編輯器裡面輸入以下內容(以GNOME為例):

#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
gnome-session

儲存並退出(在nano中按Ctrl + O儲存,然後按Ctrl + X退出)。

  1. 給予執行許可權:

為xstartup檔案設定執行許可權:

chmod +x ~/.vnc/xstartup
  1. 啟動VNC伺服器:
vncserver -geometry 1920x1080 -localhost=0

geometry 選項指定視窗大小,localhost 選項設為 0 以開放連線。(設為1是隻允許本地連線)

你將看到類似於:1的輸出,這表示VNC會話的顯示編號。例如,如果輸出為:1,則VNC監聽的埠為5901(5900 + 顯示編號)。

  1. 檢視已開啟的VNC伺服器:
vncserver -list

  1. 連線到VNC伺服器:

使用VNC客戶端(如vncviewer)連線到VNC伺服器,輸入你的伺服器IP和埠。例如,如果伺服器IP為192.168.31.10,且顯示編號為1,你應該連線到192.168.31.10:1,或者直接輸入192.168.31.10:5901。

  1. 停止VNC伺服器:

如果需要停止VNC伺服器,可以使用以下命令:

vncserver -kill :1

將:1替換為你實際使用的顯示編號。

4.開關圖形介面

可以先看當前預設模式:

systemctl get-default

如果是graphical.target就是有圖形模式,如果是multi-user.target就是命令列模式。

關掉圖形介面(設定為命令列模式):

sudo systemctl isolate multi-user.target

預設關閉圖形介面(預設進入命令列模式):

sudo systemctl set-default multi-user.target

重啟

sudo reboot

5.USB裝置名持久化

5.1.USB埠設定

在 Linux 中,USB 序列埠裝置插拔之後,系統分配的裝置節點可能會發生變化,例如:

/dev/ttyUSB0
/dev/ttyUSB1
/dev/ttyACM0
/dev/ttyACM1

如果程式、ROS 節點或者啟動指令碼直接寫死 /dev/ttyUSB0,當裝置重新插拔、增加新的 USB 裝置或者系統啟動順序發生變化時,就可能出現埠號改變的問題。

因此,在機器人、無人車、嵌入式裝置等場景中,一般需要給 USB 裝置建立一個穩定的裝置路徑或固定別名。

常見方案主要有:

  1. 使用 Linux 自動生成的 /dev/serial/by-id/;
  2. 使用 Linux 自動生成的 /dev/serial/by-path/;
  3. 根據裝置的 idVendor、idProduct、serial 等屬性編寫 udev 規則;
  4. 根據主機 USB 物理介面的位置編寫 udev 規則;
  5. 對攝像頭等裝置使用 /dev/v4l/by-id/ 或 /dev/v4l/by-path/。

5.1.1.首先配置序列埠許可權

Linux 下普通使用者預設可能沒有序列埠裝置的訪問許可權,因此首先將當前使用者加入 dialout 使用者組。

#### 将当前用户加入 dialout 用户组
sudo usermod -aG dialout $USER

#### 临时在当前终端加载新的用户组
newgrp dialout

#### 查看当前用户组中是否存在 dialout
groups

如果輸出中包含:

dialout

說明當前終端已經具有序列埠訪問許可權。

也可以登出當前桌面會話後重新登入,使使用者組許可權在整個使用者會話中生效。


5.2.優先使用 Linux 自帶的固定裝置路徑

在自己編寫 udev 規則之前,建議首先檢視系統是否已經為裝置生成了穩定的符號連結。

對於 USB 序列埠裝置:

ls -l /dev/serial/by-id/
ls -l /dev/serial/by-path/

例如:

usb-1a86_USB_Serial-if00-port0 -> ../../ttyUSB0
usb-STMicroelectronics_STM32_Virtual_ComPort_123456-if00 -> ../../ttyACM0

其中:

  • /dev/serial/by-id/:主要根據裝置本身的身份資訊生成;
  • /dev/serial/by-path/:主要根據裝置連線到主機的 USB 物理路徑生成。

5.2.1.使用 /dev/serial/by-id/

如果裝置具有穩定且唯一的序列號,通常優先使用:

/dev/serial/by-id/xxx

例如:

/dev/serial/by-id/usb-STMicroelectronics_STM32_Virtual_ComPort_123456-if00

即使對應的裝置節點從:

/dev/ttyACM0

變成:

/dev/ttyACM2

by-id 路徑通常仍然保持不變。

因此,ROS 2 引數中可以直接寫:

port: /dev/serial/by-id/usb-STMicroelectronics_STM32_Virtual_ComPort_123456-if00

這種方案最大的優點是:

  • 不依賴 ttyUSBn 或 ttyACMn 的編號;
  • USB 裝置換到其他介面後,一般仍然能夠識別;
  • 對於有唯一序列號的裝置非常穩定;
  • 不需要自己編寫 udev rules。

5.2.2.使用 /dev/serial/by-path/

如果裝置沒有唯一序列號,或者系統無法通過裝置本身區分多臺完全相同的裝置,可以使用:

/dev/serial/by-path/

檢視:

ls -l /dev/serial/by-path/

例如:

pci-0000:00:14.0-usb-0:3:1.0-port0 -> ../../ttyUSB0
pci-0000:00:14.0-usb-0:4:1.0-port0 -> ../../ttyUSB1

這種方式實際上是根據:

裝置插在主機的哪個 USB 介面

來區分裝置。

例如無人車有兩個完全相同的雷達:

前雷达 -> 固定插在 USB 口 A
后雷达 -> 固定插在 USB 口 B

此時可以直接在程式中使用兩個不同的 by-path 路徑。

缺點是:

如果交換 USB 介面,裝置對應的邏輯身份也會發生變化。


5.3.檢視 USB 裝置資訊

5.3.1.使用 lsusb

接入 USB 裝置之後,可以首先執行:

lsusb

例如:

Bus 001 Device 007: ID 1a86:7523 QinHeng Electronics CH340 serial converter

其中:

1a86:7523

分別對應:

idVendor  = 1a86
idProduct = 7523

需要注意:

idVendor + idProduct 只能表示某一類 USB 產品,通常不能唯一表示某一個具體裝置。

例如兩塊完全相同的 CH340:

CH340 A -> 1a86:7523
CH340 B -> 1a86:7523

它們的 idVendor 和 idProduct 是完全相同的。

因此:

  • 不同型號裝置可以通過 idVendor + idProduct 區分;
  • 多個相同型號裝置不能只依賴 idVendor + idProduct 區分。

5.3.2.檢視裝置完整屬性

對於序列埠裝置,可以使用:

udevadm info --query=property --name=/dev/ttyACM0

或者:

udevadm info --query=property --name=/dev/ttyUSB0

只查看常用資訊:

udevadm info --query=property --name=/dev/ttyACM0 \
    | grep -E 'ID_(VENDOR_ID|MODEL_ID|SERIAL|SERIAL_SHORT|PATH|USB_INTERFACE_NUM)'

常見輸出:

ID_VENDOR_ID=0483
ID_MODEL_ID=5740
ID_SERIAL=STMicroelectronics_STM32_Virtual_ComPort_123456
ID_SERIAL_SHORT=123456
ID_PATH=pci-0000:00:14.0-usb-0:3:1.0
ID_USB_INTERFACE_NUM=00

常用屬性說明:

屬性 含義
ID_VENDOR_ID USB 廠商 ID
ID_MODEL_ID USB 產品 ID
ID_SERIAL 完整裝置序列資訊
ID_SERIAL_SHORT USB 裝置序列號
ID_PATH 裝置連線到主機的物理路徑
ID_USB_INTERFACE_NUM USB Interface 編號

5.3.3.檢視 udev 可匹配屬性

如果需要自己編寫 udev 規則,可以使用:

udevadm info -a -p $(udevadm info -q path -n /dev/ttyACM0)

或者:

udevadm info -a -p $(udevadm info -q path -n /dev/ttyUSB0)

也可以使用:

udevadm info --attribute-walk --name=/dev/ttyUSB0

例如只查看 KERNELS:

udevadm info --attribute-walk --name=/dev/ttyUSB0 | grep KERNELS

這些資訊可以用於編寫自定義 udev rules。


5.4.根據 USB 裝置型號繫結埠

5.4.1.需求

Ubuntu 系統中連線一臺雷達和一臺智慧小車,兩臺裝置型號不同,希望給它們建立固定別名。

例如:

雷达 -> /dev/mylidar
小车 -> /dev/mycar

5.4.2.查詢 idVendor 和 idProduct

呼叫:

lsusb

假設得到:

雷达:10c4:ea60
小车:1a86:7523

其中:

10c4 -> idVendor
ea60 -> idProduct

1a86 -> idVendor
7523 -> idProduct

5.4.3.編寫 udev 規則

在:

/etc/udev/rules.d/

目錄下建立規則檔案,例如:

sudo vim /etc/udev/rules.d/99-usb-serial.rules

輸入:

KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777", SYMLINK+="mylidar"

KERNEL=="ttyUSB*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE:="0777", SYMLINK+="mycar"

其中:

  • KERNEL:匹配 Linux 核心分配的裝置名稱;
  • ATTRS{idVendor}:USB 廠商 ID;
  • ATTRS{idProduct}:USB 產品 ID;
  • MODE:="0777":設定裝置節點許可權;
  • SYMLINK+="xxx":為裝置建立固定符號連結。

例如:

/dev/mylidar -> /dev/ttyUSB0
/dev/mycar   -> /dev/ttyUSB1

5.4.4.使規則生效

Ubuntu 和 Fedora 都可以統一使用:

sudo udevadm control --reload-rules
sudo udevadm trigger

然後重新插拔 USB 裝置。

也可以只觸發 tty 子系統:

sudo udevadm control --reload-rules
sudo udevadm trigger --subsystem-match=tty

5.4.5.測試
ls -l /dev/mylidar
ls -l /dev/mycar

或者:

readlink -f /dev/mylidar
readlink -f /dev/mycar

可能得到:

/dev/ttyUSB0
/dev/ttyUSB1

5.4.6.缺點

這種方式只適合:

不同 USB 型號的裝置。

如果接入兩臺完全相同型號的裝置:

CH340 A -> 1a86:7523
CH340 B -> 1a86:7523

那麼兩個裝置都會匹配同一條 udev rule。

因此:

KERNEL=="ttyUSB*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="mycar"

不能可靠地區分兩個完全相同的 USB 裝置。

此時需要繼續使用:

  • USB Serial Number;
  • /dev/serial/by-id/;
  • /dev/serial/by-path/;
  • 主機 USB 物理介面。

5.5.根據裝置 Serial Number 繫結埠

如果多臺裝置型號相同,但是每臺裝置具有不同的 USB 序列號,那麼這是最推薦的自定義 udev 繫結方式。

例如:

设备 A:
idVendor  = 1a86
idProduct = 55d4
serial    = 0001

设备 B:
idVendor  = 1a86
idProduct = 55d4
serial    = 0002

可以編寫:

KERNEL=="ttyACM*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d4", ATTRS{serial}=="0001", MODE:="0777", SYMLINK+="ttyACM_Lidar"

KERNEL=="ttyACM*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d4", ATTRS{serial}=="0002", MODE:="0777", SYMLINK+="ttyACM_MCU"

這樣:

/dev/ttyACM_Lidar
/dev/ttyACM_MCU

就可以穩定對應兩臺裝置。

即使:

/dev/ttyACM0
/dev/ttyACM1

的編號發生交換,兩個固定別名依然可以指向正確裝置。


5.5.1.推薦檢查方法
udevadm info --query=property --name=/dev/ttyACM0 | grep SERIAL

例如:

ID_SERIAL=STMicroelectronics_STM32_Virtual_ComPort_123456
ID_SERIAL_SHORT=123456

如果 ID_SERIAL_SHORT 是唯一的,就非常適合作為裝置標識。


5.6.根據主機 USB 物理介面繫結埠

5.6.1.需求

無人車上安裝前後兩臺完全相同型號的雷達。

兩臺雷達:

  • idVendor 相同;
  • idProduct 相同;
  • 沒有唯一 Serial Number。

此時可以根據主機 USB 介面的位置區分。


5.6.2.方法一:直接使用 /dev/serial/by-path/

首先執行:

ls -l /dev/serial/by-path/

例如:

pci-0000:00:14.0-usb-0:3:1.0-port0 -> ../../ttyUSB0
pci-0000:00:14.0-usb-0:4:1.0-port0 -> ../../ttyUSB1

可以規定:

USB 口 0:3 -> 前雷达
USB 口 0:4 -> 后雷达

程式直接使用:

/dev/serial/by-path/pci-0000:00:14.0-usb-0:3:1.0-port0
/dev/serial/by-path/pci-0000:00:14.0-usb-0:4:1.0-port0

即可。


5.6.3.方法二:根據 KERNELS 建立自定義別名

檢視第一臺裝置:

udevadm info --attribute-walk --name=/dev/ttyUSB0 | grep KERNELS

檢視第二臺裝置:

udevadm info --attribute-walk --name=/dev/ttyUSB1 | grep KERNELS

假設對應:

第一台:
KERNELS=="1-1.3:1.0"

第二台:
KERNELS=="1-1.4:1.0"

則可以建立:

sudo vim /etc/udev/rules.d/99-lidar.rules

寫入:

KERNEL=="ttyUSB*", KERNELS=="1-1.3:1.0", MODE:="0777", SYMLINK+="rplidar_front"

KERNEL=="ttyUSB*", KERNELS=="1-1.4:1.0", MODE:="0777", SYMLINK+="rplidar_back"

重新載入:

sudo udevadm control --reload-rules
sudo udevadm trigger

重新插拔之後:

ls -l /dev/rplidar_front
ls -l /dev/rplidar_back

5.6.4.缺點

這種方式繫結的是:

主機 USB 介面

而不是:

USB 裝置本身

因此裝置必須插在固定 USB 介面。

如果前後兩臺雷達交換介面:

前雷达插到后雷达 USB 口

那麼系統仍然會將該介面識別為:

/dev/rplidar_back

5.7.根據 ID_PATH 繫結埠

與使用 KERNELS 類似,也可以根據 ID_PATH 建立規則。

檢視:

udevadm info --query=property --name=/dev/ttyUSB0 | grep ID_PATH

例如:

ID_PATH=pci-0000:00:14.0-usb-0:3:1.0

可以寫:

SUBSYSTEM=="tty", ENV{ID_PATH}=="pci-0000:00:14.0-usb-0:3:1.0", MODE:="0777", SYMLINK+="rplidar_front"

另一個介面:

SUBSYSTEM=="tty", ENV{ID_PATH}=="pci-0000:00:14.0-usb-0:4:1.0", MODE:="0777", SYMLINK+="rplidar_back"

相比直接寫 KERNELS,這種寫法通常更加直觀。


5.8.綜合多個屬性繫結埠

實際工程中,可以同時匹配多個屬性。

例如:

KERNEL=="ttyACM*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d4", ATTRS{serial}=="0001", MODE:="0777", SYMLINK+="ttyACM_Lidar"

KERNEL=="ttyACM*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d4", ATTRS{serial}=="0002", MODE:="0777", SYMLINK+="ttyACM_MCU"

KERNEL=="ttyUSB*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE:="0777", SYMLINK+="ttyUSB_IMU"

也可以使用:

SUBSYSTEM=="tty", ENV{ID_VENDOR_ID}=="0483", ENV{ID_MODEL_ID}=="5740", ENV{ID_SERIAL_SHORT}=="12345678", MODE:="0777", SYMLINK+="ysu_mcu"

最終得到:

/dev/ysu_mcu

這種方式非常適合機器人專案。


5.9.推薦使用統一業務裝置名稱

對於機器人專案,不建議 ROS 2 節點直接使用:

/dev/ttyUSB0
/dev/ttyACM0

可以統一建立業務名稱,例如:

/dev/ysu_mcu
/dev/ysu_gimbal
/dev/ysu_imu
/dev/ysu_lidar_front
/dev/ysu_lidar_back

例如:

SUBSYSTEM=="tty", ENV{ID_VENDOR_ID}=="0483", ENV{ID_MODEL_ID}=="5740", ENV{ID_SERIAL_SHORT}=="12345678", MODE:="0777", SYMLINK+="ysu_mcu"

SUBSYSTEM=="tty", ENV{ID_VENDOR_ID}=="10c4", ENV{ID_MODEL_ID}=="ea60", ENV{ID_SERIAL_SHORT}=="ABCDEF", MODE:="0777", SYMLINK+="ysu_imu"

SUBSYSTEM=="tty", ENV{ID_PATH}=="pci-0000:00:14.0-usb-0:3:1.0", MODE:="0777", SYMLINK+="ysu_lidar_front"

然後 ROS 2 引數寫:

serial_port: /dev/ysu_mcu
imu_port: /dev/ysu_imu
lidar_port: /dev/ysu_lidar_front

這樣後續更換裝置節點編號時,ROS 2 配置檔案完全不需要修改。


5.10.ttyUSB 與 ttyACM 的區別

並非所有 USB 序列埠裝置都使用:

/dev/ttyUSBn

常見型別如下:

裝置型別 核心名稱示例 說明
USB 轉序列埠晶片 ttyUSB* CH340、CP210x、FTDI 等
USB CDC ACM ttyACM* STM32 CDC、Arduino 等
主機物理序列埠 ttyS* PC 板載 UART
USB 攝像頭 video* V4L2 攝像頭
磁碟 sd* USB 硬碟、U 盤
輸入裝置 event* 鍵盤、滑鼠、手柄
藍牙序列埠 rfcomm* Bluetooth RFCOMM

所以 udev 規則中的:

KERNEL=="ttyUSB*"

並不是固定寫法。

如果 STM32 CDC 對應:

/dev/ttyACM0

則應該匹配:

KERNEL=="ttyACM*"

也可以統一使用:

SUBSYSTEM=="tty"

再配合其他屬性進行篩選。


5.11.USB 攝像頭固定裝置路徑

USB 攝像頭通常對應:

/dev/video0
/dev/video1
/dev/video2
...

而且一臺攝像頭有時會生成多個 /dev/videoN 節點。

因此不建議簡單假設:

video0、video2、video4 一定是摄像头采集节点

因為裝置節點編號與介面順序可能發生變化。


5.11.1.檢視系統生成的攝像頭固定路徑

執行:

ls -l /dev/v4l/by-id/
ls -l /dev/v4l/by-path/

例如:

/dev/v4l/by-id/usb-USB_Camera-video-index0
/dev/v4l/by-id/usb-USB_Camera-video-index1

如果攝像頭具有唯一身份資訊,推薦使用:

/dev/v4l/by-id/

如果需要按照固定 USB 介面區分:

/dev/v4l/by-path/

5.11.2.檢視攝像頭節點

可以安裝:

sudo apt install v4l-utils

然後:

v4l2-ctl --list-devices

例如:

USB Camera:
    /dev/video0
    /dev/video1

也可以進一步檢視某個節點支援的格式:

v4l2-ctl -d /dev/video0 --all

5.12.磁碟裝置的固定路徑

對於 USB 硬碟、U 盤、SSD 等,不建議直接依賴:

/dev/sda
/dev/sdb

Linux 同樣提供:

/dev/disk/by-id/
/dev/disk/by-path/
/dev/disk/by-uuid/
/dev/disk/by-label/

例如:

ls -l /dev/disk/by-id/

因此,不同型別裝置都遵循類似原則:

动态设备节点
        ↓
系统生成固定路径
        ↓
必要时自己编写 udev rule

5.13.使 udev 規則生效

修改:

/etc/udev/rules.d/*.rules

之後,Ubuntu 和 Fedora 均可以使用:

sudo udevadm control --reload-rules
sudo udevadm trigger

然後重新插拔裝置。

對於序列埠裝置,也可以:

sudo udevadm trigger --subsystem-match=tty

如果規則仍然沒有生效,可以直接重啟系統。


5.14.測試固定別名

檢視符號連結:

ls -l /dev/ysu_mcu

檢視最終實際裝置:

readlink -f /dev/ysu_mcu

例如:

/dev/ttyACM1

即使之後重新插拔裝置變成:

/dev/ttyACM3

如果 udev 規則匹配正確:

/dev/ysu_mcu

仍然會指向正確裝置。


5.15.排查 udev 規則

如果規則沒有生效,可以按照下面的方法檢查。


5.15.1.檢查規則語法
sudo udevadm verify /etc/udev/rules.d/99-usb-serial.rules

如果當前系統版本支援該命令,可以直接檢查規則檔案。


5.15.2.檢視裝置屬性
udevadm info --query=property --name=/dev/ttyUSB0

或者:

udevadm info --attribute-walk --name=/dev/ttyUSB0

重點檢查:

idVendor
idProduct
serial
ID_SERIAL
ID_SERIAL_SHORT
ID_PATH
KERNELS
SUBSYSTEM

5.15.3.監控裝置插拔事件

執行:

udevadm monitor --environment --udev

然後重新插拔 USB 裝置。

可以觀察系統識別裝置時生成的 udev 屬性。


5.15.4.檢視裝置實際許可權
ls -l /dev/ttyUSB0

例如:

crwxrwxrwx 1 root dialout ...

如果規則中使用:

MODE:="0777"

裝置重新生成後會按照規則設定許可權。


5.16.推薦選擇順序

USB 裝置固定埠時,推薦按照下面的順序選擇。

                USB设备
                   │
                   ▼
       是否已有系统固定路径?
         /dev/serial/by-id
                   │
             ┌─────┴─────┐
             │           │
            有           无
             │           │
             ▼           ▼
          直接使用     是否存在唯一Serial?
                         │
                   ┌─────┴─────┐
                   │           │
                  有           无
                   │           │
                   ▼           ▼
             按Serial绑定   是否固定USB接口?
                               │
                         ┌─────┴─────┐
                         │           │
                        是           否
                         │           │
                         ▼           ▼
                    by-path/      尽量从设备固件
                    ID_PATH       层增加唯一Serial

簡單來說:

能夠識別裝置本身,就按裝置本身繫結;無法識別裝置本身,就按裝置連線的 USB 介面繫結。


5.17.最終推薦方案

5.17.1.情況一:單個裝置,具有唯一 Serial

首選:

/dev/serial/by-id/

或者自己建立:

/dev/ysu_mcu

5.17.2.情況二:多個不同型號裝置

可以使用:

idVendor + idProduct

建立自定義 udev rule。


5.17.3.情況三:多個相同裝置,但 Serial 不同

使用:

idVendor + idProduct + serial

這是非常穩定的方案。


5.17.4.情況四:多個完全相同裝置,沒有唯一 Serial

使用:

/dev/serial/by-path/

或者:

KERNELS
ID_PATH

根據主機 USB 物理介面區分。


5.17.5.情況五:STM32 自定義 USB CDC

如果裝置韌體由自己控制,推薦在 USB Descriptor 中配置唯一 Serial Number。

這樣 Linux 可以根據裝置自身身份建立穩定路徑,例如:

/dev/serial/by-id/usb-STMicroelectronics_STM32_Virtual_ComPort_xxxxx-if00

之後無論插在哪一個 USB 介面,都可以識別同一塊控制板。


5.18.總結

Linux USB 裝置的固定命名,本質上可以分為兩類:

根据设备是谁
    ↓
by-id
Serial Number
idVendor + idProduct + serial


根据设备插在哪里
    ↓
by-path
ID_PATH
KERNELS

工程中建議優先順序:

/dev/serial/by-id/
        ↓
唯一 Serial Number
        ↓
/dev/serial/by-path/
        ↓
自定义 udev rules

而在機器人專案中,最終可以統一建立:

/dev/ysu_mcu
/dev/ysu_gimbal
/dev/ysu_imu
/dev/ysu_lidar_front
/dev/ysu_lidar_back

之後 ROS 2、C++ 程式和啟動檔案全部使用這些固定名稱,而不再依賴:

/dev/ttyUSB0
/dev/ttyUSB1
/dev/ttyACM0
/dev/ttyACM1

這樣即使 USB 裝置重新插拔、啟動順序發生變化或者系統重新分配埠編號,也不會影響上層程式。

6.Linux分割槽Gui工具

sudo apt install gparted
sudo dnf install gparted

7.DDNS

8.掛載內網網頁

可以把本地的網頁掛載到路由器端,或者同內網段其他裝置上,甚至可以掛載在本地。

下面以安卓裝置為例子,由於安卓裝置暫時不能直接開啟html,所以我們可以把html掛載到本地伺服器,再通過瀏覽器檢視。

由於安卓系統基於Linux核心,所以我們可以下載一個叫termux的app來敲一些Linux命令:

https://github.com/termux/termux-app

首先開啟app後,先更新軟體快取:

pkg update

然後換源

nano $PREFIX/etc/apt/sources.list

將該檔案內容替換為下面:

deb https://mirrors.bfsu.edu.cn/termux/termux-packages-24 stable main
  • 如果你使用的是nano編輯器:

    • 按 Ctrl+O 儲存檔案。

    • 按 Enter 確認檔名。

    • 按 Ctrl+X 退出編輯器。

  • 如果你使用的是vim編輯器:

    • 按 Esc 退出編輯模式。

    • 輸入 :wq 儲存並退出。

接下來重新更新軟體源:

pkg update && pkg upgrade

安裝python:

pkg install python3

通過Termux訪問裝置儲存 :

如果檔案在安卓裝置上,可以使用Termux的檔案管理器訪問裝置的儲存:

termux-setup-storage
  1. 進入HTML檔案所在的目錄 :

    1. 使用cd命令進入HTML檔案所在的目錄:
cd ~/your_html_folder
  1. 啟動Python HTTP伺服器 :

    1. 執行以下命令啟動一個簡單的HTTP伺服器:
    python3 -m http.server 8000
    1. 這會在埠8000上啟動一個Web伺服器。
  • 啟動伺服器後,Termux會顯示日誌資訊,例如:
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
  • 這表示伺服器已成功啟動。

在瀏覽器中訪問HTML檔案

  1. 在同一裝置上訪問 :

    1. 開啟安卓裝置上的瀏覽器(如Chrome),輸入以下地址:
    http://localhost:8000
    1. 如果HTML檔案中有index.html,它會自動載入;否則,你需要手動點選檔案連結。

9.RustDesk

9.1.RustDesk無人值守遠端控制

目前rustdesk還沒辦法進行無人值守在wayland下,所以我們需要把登陸密碼,鎖屏和休眠待機全部關掉.

9.1.1.設定 KDE6 自動登入
  1. 可以先查自己的sddm型別
ls /usr/share/xsessions/
ls /usr/share/wayland-sessions/

看哪個會輸出東西,輸出東西的資料夾就是你擁有的sddm,比如xsessions輸出內容的話,那就是x11的sddm,如果wayland-sessions輸出內容的話你就是wayland的sddm.

  1. 編輯 SDDM 配置:
sudo nano /etc/sddm.conf

在檔案最上面有個[Autologin],在這個底下加入下面的內容:

[Autologin]
User=你的用户名
Session=plasma.desktop   # 或 plasma.desktop(X11),方案一可用 Wayland
  1. 儲存退出後重啟 SDDM:
sudo systemctl restart sddm

✅ 開機後自動進入桌面,無需輸入密碼

9.1.2.關閉鎖屏在 KDE6 系統設定裡:

開啟 系統設定 → 螢幕鎖定(Screen Locking) 關閉自動鎖定 關閉螢幕關閉 / 螢幕保護鎖定 這樣 RustDesk 可以開機後直接控制桌面,不會被鎖屏阻擋

9.1.3.關閉休眠系統設定 → 電源管理(Power Managerment)

停用“休眠”或“自動掛起” 保證電腦開機一直線上,RustDesk 可隨時遠控 如果必須休眠,可在 BIOS 設定裡停用休眠,保證開機即聯網

9.2.RustDesk自建伺服器

9.2.1.在伺服器端安裝
9.2.1.1.命令列方式
  1. 開啟官網:https://rustdesk.com/docs/zh-cn/self-host/

alt text

  1. 用ssh訪問你需要安裝RustDesk的伺服器
ssh tungchiahui@10.0.0.4

alt text

  1. 使用方法二的命令

alt text

wget https://raw.githubusercontent.com/techahold/rustdeskinstall/master/install.sh
chmod +x install.sh
./install.sh

./install.sh的設定看下一節

  1. 配置與檢視KEY

這裡如果你是想直接用公網ip則選擇1)IP,如果你是DDNS等用域名綁定了IP地址,則選擇2).

alt text

這個選2)No

alt text

這個是KEY,要複製下來,等後面軟體配置的時候要用.

alt text

  1. 配置防火牆

    1. 如果你是Debian系 安裝防火牆
    sudo apt install ufw

    配置防火牆

    sudo ufw allow 22
    
    ufw allow 21114:21119/tcp
    ufw allow 21116/udp
    sudo ufw enable
    1. 如果你是RHEL系 安裝防火牆
    # 如果你是RHEL系
    sudo dnf install firewalld
    sudo systemctl enable --now firewalld

    配置防火牆

    sudo firewall-cmd --add-port=22/tcp --permanent
    sudo firewall-cmd --reload
    
    sudo firewall-cmd --add-port=21114-21119/tcp --permanent
    sudo firewall-cmd --reload
    
    sudo firewall-cmd --add-port=21116/udp --permanent
    sudo firewall-cmd --reload
    
    sudo systemctl enable --now firewalld
9.2.1.2.1Panel方式
  1. 在面板裡搜RustDesk並安裝

alt text

  1. 配置防火牆

alt text

新增幾個埠 alt text alt text alt text

  1. 檢視KEY alt text

複製KEY

alt text

9.2.2.自建伺服器後配置RustDesk軟體
  1. PC端

alt text

alt text

出現就緒就是配置成功了 alt text

  1. 移動端

alt text

alt text

9.2.2.1.注意的問題

如果你是家庭的內網伺服器,則需要讓路由器也放行對應埠

找到openwrt防火牆設定,點選新增 alt text

alt text

alt text

然後還有ipv6也要進行放行,那個debian一般預設ipv6不設防,但是會被上游openwrt防住,所以,要在openwrt裡開啟對應規則。

去防火墙 - 通信规则裡新增下面倆配置。

Allow-RustDesk-IPv6-TCP
WAN → LAN
目标:你服务器的ipv6公网
TCP 21115-21119
动作:接受转发

Allow-RustDesk-IPv6-UDP
WAN → LAN
目标:你服务器的ipv6公网
UDP 21116
动作:接受转发

這樣才可以讓你的伺服器埠被真正成功放行.

10.WireGuard

10.1.簡介

WireGuard是用於在室外通過VPN來訪問內網裝置的一種工具.

這裡我的教程將會教你如何在室外訪問你家裡的內網裝置.

10.2.我的環境

10.2.1.內網

家庭內網網段:10.0.0.0/24

alt text

10.2.2.外部裝置

如果你是在辦公室等地方連結辦公室的wifi,那麼你需要知道室外内网网段,如果你直接用手機資料流量的話,那麼什麼都不需要知道.

室外內網網段:192.168.31.0/24 室外資料流量運營商:中國聯通

10.3.安裝

10.3.1.服務端-軟路由端

SSH登入OpenWrt,或者用LuCI介面:

opkg update
opkg install wireguard-tools luci-proto-wireguard kmod-wireguard qrencode

裝完重新整理一下瀏覽器LuCI頁面.

10.3.2.客戶端-手機,電腦端

https://www.wireguard.com/install/

  1. Android

https://play.google.com/store/apps/details?id=com.wireguard.android&hl=zh&pli=1

  1. iOS

美區:https://apps.apple.com/us/app/wireguard/id1441195209 日區:https://apps.apple.com/jp/app/wireguard/id1441195209 臺區:https://apps.apple.com/tw/app/wireguard/id1441195209

  1. Linux

    1. Fedora
     sudo dnf install wireguard-tools
    
    1. Ubuntu/Debian
sudo apt install wireguard

10.4.配置

10.4.1.服務端-初始化配置

在luci介面中,點選网络 → 接口 → 添加新接口

  1. 協議選 WireGuard VPN
  2. 名稱填 wg0
  3. 點下一步,進到詳情頁

alt text

按照上圖的步驟,依次配置. 這裡解釋一下. 監聽埠:51820(可自定義,使用一個未被佔用的埠即可,記住這個埠,不懂的話就照我的設定) IP地址:10.10.10.1/24(VPN內網網段,跟你軟路由的區域網段不能衝突,不懂的話就照我的設定)

你必須確保你的家庭内网网段和你的室外内网网段以及剛才填的那個IP地址不能屬於同一網段.

比如我的家庭内网网段是10.0.0.0/24,而室外内网网段是192.168.31.0/24,VPN的網段10.10.10.0/24.

然後點選防火牆設定,選擇WireGuard.

alt text

10.4.2.服務端-對端配置

這裡配置的就是你的手機/筆記本作為客戶端連進來的資訊:

這個介面很方便,LuCI可以直接幫你生成客戶端的金鑰對並直接匯出配置檔案/二維碼,不需要你手動在手機上先生成公鑰再倒騰過來,效率高很多。按下面順序填:

  1. 描述 phone (或者你自己好記的名字,比如"iPhone17")
  2. 公鑰 + 私鑰 —— 直接點"生成新的金鑰對" 點這個按鈕,系統會自動幫你同時生成一對新的公鑰+私鑰,並自動填到"公鑰"和"私鑰"兩個框裡。 這個做法比你自己在手機App裡生成再抄公鑰過來省事得多,因為最後可以直接匯出完整配置檔案甚至二維碼給手機掃碼匯入,私鑰也是配置好的,不用手動輸入。
  3. 預共享金鑰(PSK) —— 建議點"生成預共享金鑰" 這是可選的額外加密層,加上更安全(抗未來量子計算破解),點一下"生成預共享金鑰"按鈕自動填好即可,不需要手動操作。
  4. 允許的IP 點綠色+號,填: 10.10.10.2/32 這是分配給這臺手機的隧道內網IP(如果以後要加第二臺裝置,比如筆記本,就用10.10.10.3/32,以此類推)。
  5. 為允許的IP建立路由 —— 勾選 這個決定了服務端要不要給這個IP自動建路由,勾上,否則服務端不知道怎麼把去往10.10.10.2的包轉發給這個peer。
  6. 對端地址 (Image 2) 這個欄位填的是客戶端的地址,但因為你的手機是移動裝置、IP會變,服務端這邊留空即可,不用填。(這個欄位一般是給"兩個固定IP的伺服器互聯"場景用的,你這種手機/筆記本客戶端場景不需要)
  7. 對端埠 同理,留空或者保持預設51820佔位符不用管,服務端這邊這個欄位對客戶端場景沒意義,跳過。
  8. 持續保持連線(Persistent Keepalive) 填: 25 因為手機大機率處在NAT環境下(無論是WiFi還是4G/5G),這個值能防止連線因為長時間無流量被NAT裝置判定斷開。
  9. 儲存後 —— 點"生成配置..." 這一步是重點:全部填完先點右下角"儲存",儲存完之後再進來點 配置匯出 那個"生成配置..."按鈕,系統會:

自動生成一份完整的客戶端配置檔案(包含私鑰、服務端公鑰、Endpoint地址等全部資訊) 通常還會顯示一個二維碼

手機WireGuard App直接掃這個二維碼就能一鍵匯入配置,完全不用你手動輸入任何欄位,最省事。

  1. 填完這些儲存之後,點"生成配置"

    alt text

    1. 連線端點 —— 改成DDNS域名 沒有ddns域名的請看ddns教程. 現在顯示的是 112.233.39.5 這個具體的公網IPv4,這是系統自動探測到的當前公網IP,但建議改成:ddns.xxxxxx.cn 原因很簡單:家庭寬頻的公網IP大機率是動態的(如果你是中國移動,你完全不需要擔心這件事情,你沒有公網ipv4,你只有公網ipv6),過一陣子運營商重新分配IP後,這個寫死的IP就失效了,配置檔案也就廢了。用DDNS域名的話,只要你路由器上的DDNS客戶端正常更新,域名自動跟著IP變化解析,配置檔案永久有效,不用來回改。 直接把這個下拉框裡的值改成 ddns.tungchiahui.cn 即可,如果下拉框裡沒有這個選項,看能不能手動輸入替換。
    2. 允許的IP —— 這個要看你的使用需求,建議改 現在是 0.0.0.0/0 + ::/0,意思是全域性代理模式:連上VPN後,手機/電腦的所有上網流量(刷網頁、看影片、聊天全部)都會先繞道回你家裡,再從家裡的網路出去上網。 這跟最初的需求("在外面訪問家裡NAS")不太一致,全域性模式的影響:

    ✅ 優點:所有流量都通過加密隧道,公共WiFi環境下更安全 ❌ 缺點:手機所有網路流量的速度都取決於你家寬頻的上傳頻寬,如果你家是常見的百兆寬頻(上傳可能才幾十M甚至更低),刷影片、下載會明顯變慢;而且家裡NAT要承擔所有流量的轉發壓力

    如果你只是想訪問家裡內網的NAS/PVE/Debian,建議改成分離隧道模式,把這兩行改成: 10.10.10.0/24 10.0.0.0/24 刪掉 0.0.0.0/0 和 ::/0 這兩行(點它們右邊的紅色×號),只保留上面這兩個網段。這樣只有"訪問家裡內網"這一類流量才走VPN隧道,其他正常上網流量不受影響,速度不受影響。 如果你確實希望VPN也當"全域性代理"用(比如出門用境外的WiFi想用家裡的網路環境訪問某些內容),那就保留 0.0.0.0/0 不用改。

    1. DNS伺服器:10.0.0.1 —— 這是你家庭內網的軟路由的LAN地址,連VPN後用它解析域名沒問題,能順帶解析你家內網可能配置的一些本地域名
    2. 地址:10.10.10.2/32 —— 這個就是你想給你的這個手機分配一個VPN網段

alt text

然後掏出手機的客戶端,使用QRcode匯入配置即可.

alt text

10.4.3.服務端-防火牆設定

需要加的規則 去 網路 → 防火牆 → 通訊規則(Traffic Rules),點"新增":

alt text

名稱:WireGuard(隨便起) 協議:UDP 或者 TCP/UDP 源區域:wan 目標區域:裝置(輸入) —— 因為WireGuard監聽的是軟路由本機埠,不是轉發給內網其他裝置 目標埠:51820(跟你wg0介面"監聽埠"那裡填的一致) 操作:接受(Accept)

alt text

儲存,應用。

10.4.4.客戶端

拿iOS舉例子

我這裡使用資料流量來測試,使用的是中國聯通4G.

像使用普通的VPN一樣開啟你匯入的這個配置即可.

alt text

10.5.測試

然後可以嘗試訪問你的內網裝置, 比如我的 openwrt是10.0.0.1, pve是10.0.0.2, nas是10.0.0.5都可以被正常訪問了.

alt text

alt text

alt text

10.6.將WireGuard交由Clash Meta管理(可選)

10.6.1.將純WireGuard配置放入Clash Meta

如果手機或電腦上已經長期執行支援Mihomo / Clash Meta核心的客戶端,再單獨啟動WireGuard客戶端會比較麻煩,而且同一臺移動裝置通常不能同時啟用兩個VPN隧道。

因此,可以將WireGuard節點直接寫入Clash Meta配置,讓Clash Meta統一負責:

  1. 普通網際網路流量直連;
  2. 家庭內網流量通過WireGuard訪問;
  3. 根據規則自動判斷流量應該走哪個出口。

本節只介紹不包含機場或其他代理節點的純WireGuard配置。

配置完成後,不再需要開啟獨立的WireGuard客戶端。使用該配置時,應關閉WireGuard App中的隧道,只打開Clash Meta。

10.6.1.1.檢視WireGuard客戶端引數

先開啟已經能夠正常使用的WireGuard客戶端配置,需要記錄以下資訊:

Clash Meta欄位 WireGuard客戶端中的對應欄位
server Peer中的Endpoint域名或公網IP
port Peer中的Endpoint埠
ip Interface中的Addresses,只填寫IPv4地址,不寫/32
private-key Interface中的Private key
public-key Peer中的Public key,也就是WireGuard伺服器公鑰
pre-shared-key Peer中的Preshared key
persistent-keepalive Peer中的Persistent keepalive

這裡最容易弄錯的是兩個公鑰:

  • Interface中的Public key是當前客戶端的公鑰,不能填入Clash Meta的public-key;
  • Peer中的Public key才是WireGuard伺服器公鑰,需要填入Clash Meta的public-key。

WireGuard客户端参数位置

這一張圖同時包含Interface和Peer兩部分,已經足夠說明各個欄位應該從哪裡獲取,不需要再增加其他截圖。

10.6.1.2.建立YAML配置

新建一個副檔名為.yaml的檔案,例如:

home-wireguard.yaml

寫入下面的模板:

# 仅让家庭内网流量通过WireGuard
# 普通互联网流量保持直连
# 启用本配置时,不要同时开启独立的WireGuard客户端

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: true

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true

proxies:
  - name: 家庭-WG
    type: wireguard

    # WireGuard客户端Peer中的Endpoint
    server: ddns.example.com
    port: 51820

    # WireGuard客户端Interface中的Addresses
    # 例如原配置为10.10.10.2/32,这里只填写10.10.10.2
    ip: 10.10.10.2

    # WireGuard客户端Interface中的Private key
    private-key: "gBzeTbZH..."

    # WireGuard客户端Peer中的Public key,即服务器公钥
    # 不要填写Interface中的客户端公钥
    public-key: "UUS0nrKE..."

    # WireGuard客户端Peer中的Preshared key
    pre-shared-key: "NGYvFsCle..."

    allowed-ips:
      - 0.0.0.0/0

    udp: true
    persistent-keepalive: 25
    mtu: 1380

rules:
  # 家庭局域网网段
  - IP-CIDR,10.0.0.0/24,家庭-WG,no-resolve

  # WireGuard隧道网段
  - IP-CIDR,10.10.10.0/24,家庭-WG,no-resolve

  # 其他网络流量保持直连
  - MATCH,DIRECT
10.6.1.3.修改模板中的引數

需要按照自己的WireGuard配置修改以下內容。

1. server

將:

server: ddns.example.com

改成WireGuard客戶端Peer中Endpoint冒號前面的域名或公網IP。

例如Endpoint為:

ddns.example.com:51820

那麼填寫:

server: ddns.example.com

2. port

填寫Endpoint冒號後面的埠,例如:

port: 51820

3. ip

填寫WireGuard客戶端Interface中的Addresses,但不要填寫CIDR字尾。

例如原配置是:

10.10.10.2/32

Clash Meta中填寫:

ip: 10.10.10.2

4. private-key

填寫WireGuard客戶端Interface中的Private key:

private-key: "客户端私钥"

5. public-key

填寫WireGuard客戶端Peer中的Public key,也就是伺服器公鑰:

public-key: "服务器公钥"

不要誤填Interface中的Public key。Interface中的Public key屬於當前客戶端,Peer中的Public key才屬於伺服器。

6. pre-shared-key

填寫WireGuard客戶端Peer中的Preshared key:

pre-shared-key: "预共享密钥"

WireGuard金鑰是Base64字串,複製時不要漏掉末尾可能存在的=。

7. rules

將規則中的家庭區域網網段和WireGuard隧道網段改成自己的實際網段。

例如:

rules:
  - IP-CIDR,10.0.0.0/24,家庭-WG,no-resolve
  - IP-CIDR,10.10.10.0/24,家庭-WG,no-resolve
  - MATCH,DIRECT

表示:

  • 訪問10.0.0.0/24家庭區域網時走WireGuard;
  • 訪問10.10.10.0/24WireGuard隧道網段時走WireGuard;
  • 其他流量全部直連,不經過家庭寬頻。
10.6.1.4.關於allowed-ips

模板中的:

allowed-ips:
  - 0.0.0.0/0

可以保持不變。

它表示這個WireGuard代理節點能夠承載全部IPv4流量,但實際哪些流量交給WireGuard,仍然由最下面的rules決定。

例如:

rules:
  - IP-CIDR,10.0.0.0/24,家庭-WG,no-resolve
  - IP-CIDR,10.10.10.0/24,家庭-WG,no-resolve
  - MATCH,DIRECT

在這套規則下,只有家庭內網和WireGuard隧道網段走WireGuard,其他網際網路流量繼續直連。

需要注意,WireGuard服務端Peer中的Allowed IPs仍然應該是分配給該客戶端的地址,例如:

10.10.10.2/32

不要把WireGuard服務端Peer中的Allowed IPs改成0.0.0.0/0。

10.6.1.5.匯入並測試

將YAML檔案匯入支援Mihomo / Clash Meta核心的客戶端,然後:

  1. 關閉獨立的WireGuard客戶端隧道;
  2. 在Clash Meta中選擇剛才匯入的配置;
  3. 使用“規則”模式;
  4. 開啟Clash Meta連線開關;
  5. 訪問家庭內網裝置進行測試。

例如訪問軟路由:

http://10.0.0.1

或者在iOS檔案App中連線NAS:

smb://10.0.0.5

同時可以進入WireGuard服務端,檢視對應Peer的Latest Handshake。

如果開啟Clash Meta後握手時間重新整理,並且能夠訪問家庭內網裝置,就說明配置成功。

10.6.1.6.常見問題

如果YAML能夠啟動,但無法產生WireGuard握手,優先檢查:

  1. public-key是否誤填成客戶端公鑰;
  2. private-key是否為當前客戶端私鑰;
  3. pre-shared-key是否完整,末尾的=是否遺漏;
  4. ip是否與服務端分配給該Peer的地址一致;
  5. Endpoint域名和埠是否正確;
  6. 軟路由防火牆是否已經放行WireGuard埠;
  7. 獨立WireGuard客戶端是否仍然處於開啟狀態。

如果報錯類似:

decode pre shared key: illegal base64 data

通常說明pre-shared-key複製不完整,常見原因是末尾的=被遺漏。

10.6.2.將WireGuard加入包含代理節點的YAML

11.Alist

11.1.簡介

11.2.安裝

11.3.WebUI

11.4.S3協議

11.4.1.開啟S3

先進行使能S3協議。

去/opt/1panel/apps/alist/alist/data/data目錄修改掉如下圖的設定從false改成true。

"s3": {
  "enable": true,
  "port": 5246,
  "ssl": false
}

最後點選重啟。

11.4.2.測試S3連結

在部署AList伺服器本身敲

curl -i http://127.0.0.1:5246/

如果顯示HTTP/1.1 200 OK,那證明是OK的。

後續我也把他反向代理成了一個域名s3.tungchiahui.cn,經測試,也沒毛病:

11.4.3.配置S3

在AList的管理介面找到設定裡的S3,然後點底下的Add來新增哪個路徑為桶:

  • Name就是桶的名字
  • Path是你想讓AList的哪個路徑作為桶子的根目錄
  • S3 access key id 是S3授權ID
  • S3 secret access key是S3授權金鑰

11.4.4.測試S3

先準備好你的配置

Endpoint:
http://127.0.0.1:5246
或者
https://s3.tungchiahui.cn

Bucket:
ObjectStorage

Access Key:
AList 后台生成的 S3 Access Key ID

Secret Key:
AList 后台生成的 S3 Secret Access Key

Region:
us-east-1

使用一個可以使用S3的軟體,比如我使用我做的VScode外掛來進行測試。

外掛連結如下: https://marketplace.visualstudio.com/items?itemName=tungchiahui.md-image-uploader

我把配置填到了VScode中的settings.json使用我的外掛進行了測試:

{
  "mdImageUploader.s3.accessKeyId": "2Vxxxxxxxxxxxxxxxxxxxxxx",
  "mdImageUploader.s3.secretAccessKey": "FWx6xxxxxxxxxxxxxxxxxx",
  "mdImageUploader.s3.endpoint": "https://s3.tungchiahui.cn",
  "mdImageUploader.s3.region": "us-east-1",
  "mdImageUploader.s3.bucket": "ObjectStorage",
  "mdImageUploader.cdnUrl": "https://cdn.tungchiahui.cn",
  "mdImageUploader.datedUploadPath": "/tungwebsite/assets/images",
  "mdImageUploader.undatedUploadPath": "/tungwebsite/assets/images/undate"
}

經過測試,檔案已經成功被儲存到了桶子裡。

11.4.5.建立檔案直鏈

去AList後臺

管理
→ 设置
→ 全局
→ 关闭Sign All

如果開著 Sign All,關掉。因為只要全域性 Sign All 開著,下面單獨儲存關簽名也沒用。AList 官方明確說 Sign All 會給所有檔案直鏈添加簽名。

然後找到你的存放AList的桶子的儲存地點進行編輯。

關閉启用签名 / Enable signing。

然後儲存。

然後你可以通過![](https://alist.tungchiahui.cn/d/AList文件的路径/文件名.webp)來訪問檔案了。

高階操作(可選):

把cdn.tungchiahui.cn也和alist.tungchiahui.cn同源,然後在騰訊雲edgeone里加速,在規則引擎裡新加一個cdn路径前缀增加的規則。

  • HOST選擇cdn.tungchiahui.cn
  • 操作選回源URL重写
  • 型別選增加路径前缀
  • 增加路徑字首選/d/AList文件的多余路径/

比如增加路径前缀我填的/d/NAS/ObjectStorage, 那麼我用https://cdn.tungchiahui.cn/tungwebsite/assets/images/2024/03/30/1787159371048-e2e3749f.webp 將會同等於https://alist.tungchiahui.cn/d/NAS/ObjectStorage/tungwebsite/assets/images/2024/03/30/1787159371048-e2e3749f.webp, 都會回源到我的https://服务器ip地址/d/NAS/ObjectStorage/tungwebsite/assets/images/2024/03/30/1787159371048-e2e3749f.webp。

再設定一個快取規則:

快取規則可以這樣理解:

  • 節點快取 TTL:30 天
    EdgeOne 會把圖片快取到邊緣節點 30 天。後續訪問優先從 CDN 節點返回,可以明顯減少 AList、伺服器 和 伺服器寬頻 的壓力。

  • 強制快取:關閉
    保持關閉更穩妥。如果源站明確要求某些資源不要快取,EdgeOne 會尊重源站設定,避免把特殊資源錯誤快取。

  • Cache Key:查詢字串全部忽略
    例如:

    xxx.webp
    xxx.webp?a=1
    xxx.webp?a=2
    xxx.webp?a=3

    都會被認為是同一個快取資源。這樣可以防止別人不斷修改 URL 引數繞過快取,反覆回源打你的 AList 和 伺服器,而我這裡檔案還儲存在NAS上,也會進一步防止他反覆打我的NAS。

  • 忽略大小寫:關閉
    abc.webp 和 ABC.webp 會被當成兩個不同檔案,避免不同檔案被錯誤合併到同一個快取。

  • PHP / JSP / ASP / ASPX:不快取
    這些通常屬於動態頁面,單獨設為不快取可以防止動態內容被 CDN 長時間快取。對於純圖片 CDN 來說基本屬於防呆設定。

  • 圖片瀏覽器快取 TTL:1 天
    jpg、png、gif、bmp、svg、webp 等圖片會在使用者瀏覽器中快取 1 天。使用者短時間內重複訪問時,瀏覽器可以直接讀取本地快取,連 EdgeOne 都不用重新請求。

最終快取鏈路大致如下:

浏览器
  ↓ 本地缓存 1 天
EdgeOne
  ↓ 节点缓存 30 天
AList
  ↓
NAS

絕大多數重複訪問會停在瀏覽器或 EdgeOne,不會真正回源到家裡的 伺服器 和 NAS。

12.MinIO 自建物件儲存

12.1.簡介

專案 騰訊 COS 自建 MinIO
物件儲存 ✅ ✅
S3 API ✅ ✅
圖片/附件 ✅ ✅
Bucket ✅ ✅
SDK 上傳 ✅ ✅
私有物件/簽名 URL ✅ ✅
Versioning ✅ ✅
儲存空間 騰訊提供 吃你伺服器硬碟
頻寬 騰訊提供 吃學校伺服器出口頻寬
高可用 騰訊負責 你負責
資料冗餘 騰訊負責 你負責
硬碟損壞 雲廠商處理 可能直接丟資料
運維 幾乎沒有 Docker、磁碟、備份、升級、安全都自己搞
費用 儲存+流量 軟體可以自建,但硬碟/伺服器/頻寬自己承擔
CDN 很容易接騰訊 CDN/EO MinIO 本身不是 CDN
可控性 一般 非常高

12.2.安裝

首先你需要伺服器上安裝一個1panel.

進入商店,搜尋minio.

點選安裝.

大多數設定都預設即可,但賬號密碼要自己填寫,這個埠外部訪問這裡,如果你的伺服器在內網,可以選擇開啟,如果你的伺服器的IP是一個公網IP,那麼不建議你開啟.

配置項 建議
名稱 minio
版本 選 1Panel 當前提供的穩定版本
使用者 自己設一個,不要用太簡單的
密碼 自己設一個密碼複雜點的
WebUI 埠 9001
S3 API 埠 9000
會話持續時間 預設 12h 即可
啟用 WebUI 開
WebUI 動畫 隨意
埠外部訪問 建議不開公網暴露,但如果測試的話,先開公網暴露也可以.

最後點選安裝.

12.3.配置MinIO

12.3.1.登陸MinIO

在瀏覽器輸入服务器ip:9001:

比如我這個內網10.0.0.4:9001

然後登陸賬號密碼.

12.3.2.測試桶

建立一個桶,比如我這裡叫test

再隨便上傳一張圖片試試.

12.3.3.測試S3協議

S3協議的網址應該是服务器ip:9000:

比如我這個內網10.0.0.4:9000

在你電腦上測試 S3 API 健康狀態:

curl -i http://10.0.0.4:9000/minio/health/live

如果顯示HTTP/1.1 200 OK,那證明是OK的。

同樣,測試下面這個是否S3就緒:

curl -i http://10.0.0.4:9000/minio/health/ready

如果顯示HTTP/1.1 200 OK,那證明是OK的。

12.3.4.接入AList測試

這個一定要開著。

配置完後,可以返回檔案列表,發現剛才的檔案可以被正常查看了。