# 串口关机控制器 通过串口接收指令触发 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 静态编译,无外部依赖