238 lines
6.2 KiB
Bash
238 lines
6.2 KiB
Bash
#!/bin/bash
|
||
set -e
|
||
|
||
# ============================================
|
||
# 串口关机控制器 - 更换串口脚本
|
||
# ============================================
|
||
|
||
INSTALL_DIR="/opt/ttyshutdown"
|
||
CONFIG_FILE="${INSTALL_DIR}/config.json"
|
||
SIGNAL_SCRIPT="/usr/lib/systemd/system-shutdown/send_signal.sh"
|
||
SERVICE_NAME="ttyshutdown"
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m'
|
||
|
||
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||
error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||
|
||
# 检查 root 权限
|
||
check_root() {
|
||
if [ "$(id -u)" -ne 0 ]; then
|
||
error "请使用 root 权限运行此脚本: sudo bash change_port.sh"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# 检查是否已安装
|
||
check_installed() {
|
||
if [ ! -f "$CONFIG_FILE" ]; then
|
||
error "未找到配置文件 $CONFIG_FILE,请先运行 install.sh 安装"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# 读取当前配置
|
||
read_current_config() {
|
||
CURRENT_PORT=$(grep -oP '"port"\s*:\s*"\K[^"]+' "$CONFIG_FILE")
|
||
CURRENT_BAUD=$(grep -oP '"baudRate"\s*:\s*\K[0-9]+' "$CONFIG_FILE")
|
||
CURRENT_WORD=$(grep -oP '"shutdownWord"\s*:\s*"\K[^"]+' "$CONFIG_FILE")
|
||
|
||
echo -e "${CYAN}=== 当前配置 ===${NC}"
|
||
echo " 串口设备: $CURRENT_PORT"
|
||
echo " 波特率: $CURRENT_BAUD"
|
||
echo " 关机指令: $CURRENT_WORD"
|
||
echo ""
|
||
}
|
||
|
||
# 扫描可用串口
|
||
scan_serial_ports() {
|
||
local ports=()
|
||
for pattern in "ttyUSB*" "ttyACM*" "ttyS*"; do
|
||
for dev in /dev/$pattern; do
|
||
if [ -e "$dev" ]; then
|
||
ports+=("$dev")
|
||
fi
|
||
done
|
||
done
|
||
echo "${ports[@]}"
|
||
}
|
||
|
||
# 交互选择串口
|
||
select_serial_port() {
|
||
local ports
|
||
ports=$(scan_serial_ports)
|
||
|
||
if [ -z "$ports" ]; then
|
||
warn "未检测到串口设备"
|
||
echo -e "请手动输入串口设备路径 (如 ${YELLOW}/dev/ttyUSB0${NC}): "
|
||
read -r SELECTED_PORT
|
||
if [ ! -e "$SELECTED_PORT" ]; then
|
||
warn "设备 $SELECTED_PORT 当前不存在,仍将配置(设备可能稍后接入)"
|
||
fi
|
||
return
|
||
fi
|
||
|
||
local port_array=($ports)
|
||
echo -e "检测到以下串口设备:${GREEN}"
|
||
local i=1
|
||
for p in "${port_array[@]}"; do
|
||
local desc=""
|
||
case "$p" in
|
||
/dev/ttyUSB*) desc="USB转串口" ;;
|
||
/dev/ttyACM*) desc="USB CDC虚拟串口" ;;
|
||
/dev/ttyS*) desc="原生串口(COM口)" ;;
|
||
esac
|
||
local marker=""
|
||
if [ "$p" = "$CURRENT_PORT" ]; then
|
||
marker=" ${YELLOW}<-- 当前${NC}"
|
||
fi
|
||
echo " [$i] $p ($desc)${marker}"
|
||
((i++))
|
||
done
|
||
echo -e "${NC}"
|
||
|
||
local last_index=${#port_array[@]}
|
||
echo " [$((last_index + 1))] 手动输入其他路径"
|
||
echo ""
|
||
|
||
local choice
|
||
while true; do
|
||
read -rp "请选择串口 [1-$((last_index + 1))]: " choice
|
||
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "$((last_index + 1))" ]; then
|
||
break
|
||
fi
|
||
error "无效选择,请重新输入"
|
||
done
|
||
|
||
if [ "$choice" -le "$last_index" ]; then
|
||
SELECTED_PORT="${port_array[$((choice - 1))]}"
|
||
else
|
||
read -rp "请输入串口设备路径: " SELECTED_PORT
|
||
if [ -z "$SELECTED_PORT" ]; then
|
||
error "路径不能为空"
|
||
exit 1
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# 更新 config.json
|
||
update_config() {
|
||
local port="$1"
|
||
local baud_rate="$2"
|
||
local shutdown_word="$3"
|
||
|
||
cat > "$CONFIG_FILE" <<EOF
|
||
{
|
||
"port": "${port}",
|
||
"baudRate": ${baud_rate},
|
||
"shutdownWord": "${shutdown_word}"
|
||
}
|
||
EOF
|
||
info "已更新配置文件: $CONFIG_FILE"
|
||
}
|
||
|
||
# 更新 send_signal.sh
|
||
update_send_signal() {
|
||
local port="$1"
|
||
local baud_rate="$2"
|
||
local shutdown_word="$3"
|
||
|
||
cat > "$SIGNAL_SCRIPT" <<EOF
|
||
#!/bin/bash
|
||
|
||
TTY_DEVICE="${port}"
|
||
|
||
ACTION=\$1
|
||
|
||
if [ "\$ACTION" = "poweroff" ] ; then
|
||
if [ -w "\$TTY_DEVICE" ]; then
|
||
stty -F "\$TTY_DEVICE" ${baud_rate} cs8 -cstopb -parenb
|
||
printf "ok\r\n" > "\$TTY_DEVICE"
|
||
fi
|
||
fi
|
||
exit 0
|
||
EOF
|
||
chmod +x "$SIGNAL_SCRIPT"
|
||
info "已更新关机钩子: $SIGNAL_SCRIPT"
|
||
}
|
||
|
||
# 重启服务
|
||
restart_service() {
|
||
systemctl restart "$SERVICE_NAME"
|
||
info "已重启服务: $SERVICE_NAME"
|
||
}
|
||
|
||
# 主流程
|
||
main() {
|
||
check_root
|
||
check_installed
|
||
|
||
echo -e "${CYAN}========================================${NC}"
|
||
echo -e "${CYAN} 串口关机控制器 - 更换串口${NC}"
|
||
echo -e "${CYAN}========================================${NC}"
|
||
echo ""
|
||
|
||
# 1. 显示当前配置
|
||
read_current_config
|
||
|
||
# 2. 选择新串口
|
||
select_serial_port
|
||
|
||
if [ "$SELECTED_PORT" = "$CURRENT_PORT" ]; then
|
||
warn "选择的新串口与当前串口相同,无需更改"
|
||
exit 0
|
||
fi
|
||
|
||
info "新串口: $SELECTED_PORT"
|
||
|
||
# 3. 可选修改波特率和关机指令
|
||
local new_baud="$CURRENT_BAUD"
|
||
local new_word="$CURRENT_WORD"
|
||
|
||
echo ""
|
||
read -rp "波特率 [当前 $CURRENT_BAUD,回车保持]: " input_baud
|
||
if [ -n "$input_baud" ]; then
|
||
new_baud="$input_baud"
|
||
fi
|
||
|
||
read -rp "关机指令 [当前 $CURRENT_WORD,回车保持]: " input_word
|
||
if [ -n "$input_word" ]; then
|
||
new_word="$input_word"
|
||
fi
|
||
|
||
# 4. 确认
|
||
echo ""
|
||
echo -e "${CYAN}=== 确认更改 ===${NC}"
|
||
echo " 串口设备: $CURRENT_PORT -> $SELECTED_PORT"
|
||
[ "$new_baud" != "$CURRENT_BAUD" ] && echo " 波特率: $CURRENT_BAUD -> $new_baud"
|
||
[ "$new_word" != "$CURRENT_WORD" ] && echo " 关机指令: $CURRENT_WORD -> $new_word"
|
||
echo ""
|
||
read -rp "确认更改? [Y/n]: " confirm
|
||
if [[ "$confirm" =~ ^[Nn] ]]; then
|
||
warn "已取消"
|
||
exit 0
|
||
fi
|
||
|
||
# 5. 执行更改
|
||
update_config "$SELECTED_PORT" "$new_baud" "$new_word"
|
||
update_send_signal "$SELECTED_PORT" "$new_baud" "$new_word"
|
||
restart_service
|
||
|
||
echo ""
|
||
echo -e "${GREEN}========================================${NC}"
|
||
echo -e "${GREEN}串口更换完成!${NC},重启或重启ttyshutdown服务后生效"
|
||
echo -e "${GREEN}========================================${NC}"
|
||
echo -e " 新串口: ${CYAN}$SELECTED_PORT${NC}"
|
||
echo -e " 波特率: ${CYAN}$new_baud${NC}"
|
||
echo -e " 服务状态: ${CYAN}systemctl status ttyshutdown${NC}"
|
||
echo -e " 查看日志: ${CYAN}journalctl -u ttyshutdown -f${NC}"
|
||
}
|
||
|
||
main
|