Files
poweroff-protection/poweroff_linux/串口关机文档.md
2026-05-14 17:53:52 +08:00

244 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 串口关机控制器
通过串口接收指令触发 x86 Ubuntu 系统关机的程序。
## 功能概述
本程序持续监听指定的串口,当接收到特定的关机指令时,自动执行系统关机操作。适用于嵌入式 x86 Ubuntu 系统中需要通过外部设备(如 MCU/Arduino控制关机的场景。
程序启动后会主动发送 `start` 握手指令,并每秒定时发送 `blive` 心跳包,用于告知对端设备本机处于在线状态。
## 主要特性
- 持续监听串口数据
- 支持配置文件自定义串口参数
- 自动重连机制(串口断开后每 5 秒重新连接)
- 按行解析接收到的数据
- 串口连接后发送 `start` 握手指令
- 每秒定时发送 `blive` 心跳包
- 执行系统关机命令
## 通信协议
### 本机发送(→ 对端)
| 指令 | 触发时机 | 说明 |
|------|----------|------|
| `start\r\n` | 串口连接成功后立即发送 | 握手指令,通知对端本机已就绪 |
| `blive\r\n` | 每秒定时发送 | 心跳包,通知对端本机仍在运行 |
| `ok\r\n` | 系统关机poweroff时发送 | 关机钩子脚本发送,通知对端本机即将关机 |
### 本机接收(← 对端)
| 指令 | 说明 |
|------|------|
| `shutdownWord`(配置项) | 收到后立即触发系统关机,默认为 `SHUTDOWN` |
## 配置说明
配置文件为 `config.json`,与可执行文件放在同一目录下,包含以下参数:
| 参数 | 类型 | 说明 | 默认值 |
|------|------|------|--------|
| port | string | 串口设备路径 | `/dev/ttyUSB0` |
| baudRate | int | 串口波特率 | 115200 |
| shutdownWord | string | 触发关机的指令文本 | `SHUTDOWN` |
### 串口设备路径
x86 Ubuntu 下常见的串口设备路径格式:
| 设备类型 | 路径格式 | 说明 |
|----------|----------|------|
| USB 转串口 | `/dev/ttyUSBx` | USB-RS232/USB-TTL 转接器(如 CH340、CP2102、FT232 |
| USB CDC ACM | `/dev/ttyACMx` | USB 虚拟串口设备(使用USB时) |
| 原生串口 | `/dev/ttySx` | 主板自带 RS232 串口COM 口) |
> `x` 为设备编号,从 0 开始。可通过 `ls /dev/tty*` 或 `dmesg | grep tty` 查看系统中可用的串口设备。
### 配置示例
使用 USB 转串口:
```json
{
"port": "/dev/ttyUSB0",
"baudRate": 115200,
"shutdownWord": "SHUTDOWN"
}
```
使用 USB CDC
```json
{
"port": "/dev/ttyACM0",
"baudRate": 115200,
"shutdownWord": "SHUTDOWN"
}
```
使用主板原生串口:
```json
{
"port": "/dev/ttyS0",
"baudRate": 115200,
"shutdownWord": "SHUTDOWN"
}
```
## 交叉编译
本程序在 Windows 上开发,需要交叉编译为 x86 Linux 可执行文件:
```bash
set GOOS=linux
set GOARCH=amd64
set CGO_ENABLED=0
go build -o shutdown shutdown.go
```
PowerShell 环境:
```powershell
$env:GOOS = "linux"
$env:GOARCH = "amd64"
$env:CGO_ENABLED = "0"
go build -o shutdown shutdown.go
```
编译产物 `shutdown` 为 Linux x86_64 可执行文件,需上传至目标 Ubuntu 系统运行。
## 部署与运行
### 方式一:使用安装脚本(推荐)
项目提供 `install.sh` 安装脚本,可自动完成串口选择、配置生成、服务安装等全部流程。
#### 上传项目到目标系统
```bash
scp -r ./ user@<目标IP>:/home/user/shutdown/
```
#### 运行安装脚本
```bash
cd /home/user/shutdown
sudo bash install.sh
```
#### 安装流程
1. **选择串口** - 脚本自动扫描系统中的串口设备(`ttyUSB*``ttyACM*``ttyS*`),列出设备并标明类型,交互选择或手动输入路径
2. **配置参数** - 可自定义波特率(默认 115200和关机指令默认 SHUTDOWN
3. **确认安装** - 显示完整配置供确认
4. **自动编译** - 检测到 Go 环境则交叉编译,否则使用预编译二进制
5. **安装文件** - 二进制和配置文件安装到 `/opt/ttyshutdown/`
6. **关机钩子** - 生成 `/usr/lib/systemd/system-shutdown/send_signal.sh`,系统关机时通过串口发送 `ok\r\n` 通知对端
7. **systemd 服务** - 生成并启用 `ttyshutdown.service`
#### 安装后管理
```bash
# 查看服务状态
systemctl status ttyshutdown
# 查看实时日志
journalctl -u ttyshutdown -f
# 停止服务
systemctl stop ttyshutdown
# 更换串口
sudo bash change_port.sh
# 卸载
sudo bash uninstall.sh
```
### 更换串口
当需要更换串口设备时(如更换 USB 端口、更换转接器等),使用 `change_port.sh` 脚本可自动完成配置更新和服务重启。
```bash
sudo bash change_port.sh
```
#### 更换流程
1. **显示当前配置** - 展示当前串口设备、波特率、关机指令
2. **选择新串口** - 自动扫描系统中可用串口,当前使用的串口会标注 `<-- 当前`,交互选择或手动输入新路径
3. **可选修改参数** - 波特率和关机指令可直接回车保持不变,或输入新值修改
4. **确认更改** - 显示新旧配置对比供确认
5. **执行更改** - 同时更新 `config.json``send_signal.sh`,并自动重启 `ttyshutdown` 服务
> 脚本会同时更新 `config.json` 和 `send_signal.sh` 中的串口配置,确保两者一致。
### 方式二:手动部署
#### 1. 上传到目标系统
```bash
scp shutdown config.json user@<目标IP>:/home/user/shutdown/
```
#### 2. 添加执行权限
```bash
chmod +x shutdown
```
#### 3. 运行程序
```bash
sudo ./shutdown
```
## 注意事项
1. 程序需要 root 权限才能执行系统关机命令
2. 串口断开后会每 5 秒尝试重新连接
3. 接收的数据以换行符(`\n``\r\n`)为单位进行解析
4. 关机指令必须与配置文件中的 `shutdownWord` 完全匹配(区分大小写)
5. 串口重连后 `start` 握手和 `blive` 心跳会自动重新启动
6. 串口设备路径在设备重新插拔后可能变化ttyUSB0 → ttyUSB1建议使用 udev 规则绑定固定设备名
7. 安装脚本会将选定的串口设备同时写入 `config.json``send_signal.sh`,确保两者一致
## 日志输出
程序运行时会输出以下日志信息:
- 配置加载状态
- 串口连接状态
- `start` 握手指令发送状态
- 接收到的数据内容
- 关机指令触发和执行状态
- 串口错误和重连状态
## 关机钩子
系统关机时,`/usr/lib/systemd/system-shutdown/send_signal.sh` 会被 systemd 调用,在系统执行 poweroff 前通过串口向对端发送 `ok\r\n`,通知对端本机即将关机。
该脚本由安装脚本自动生成,其中 `TTY_DEVICE``config.json` 中的 `port` 保持一致。
## 文件说明
| 文件 | 说明 |
|------|------|
| `shutdown.go` | 主程序源码 |
| `config.json` | 串口配置文件(与二进制同目录) |
| `send_signal.sh` | systemd 关机钩子脚本,安装到 `/usr/lib/systemd/system-shutdown/` |
| `ttyshutdown.service` | systemd 服务单元文件 |
| `install.sh` | 安装脚本 |
| `uninstall.sh` | 卸载脚本 |
| `change_port.sh` | 更换串口脚本 |
## 技术实现
- 编程语言Go
- 目标平台x86 Ubuntu (linux/amd64)
- 依赖库:`go.bug.st/serial`(串口通信)
- 关机命令:`shutdown -h now`
- 交叉编译CGO_ENABLED=0 静态编译,无外部依赖