跳到正文

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測試

這個一定要開着。

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