235 lines
6.0 KiB
Bash
235 lines
6.0 KiB
Bash
#!/bin/bash
|
|
set -e
|
|
|
|
# ============================================
|
|
# 串口关机控制器 - 安装脚本
|
|
# ============================================
|
|
|
|
INSTALL_DIR="/opt/ttyshutdown"
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
# 颜色定义
|
|
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 install.sh"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 扫描可用串口
|
|
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() {
|
|
echo -e "${CYAN}========================================${NC}"
|
|
echo -e "${CYAN} 串口关机控制器 - 安装向导${NC}"
|
|
echo -e "${CYAN}========================================${NC}"
|
|
echo ""
|
|
|
|
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
|
|
echo " [$i] $p ($desc)"
|
|
((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
|
|
generate_config() {
|
|
local port="$1"
|
|
local baud_rate="$2"
|
|
local shutdown_word="$3"
|
|
|
|
cat > "${INSTALL_DIR}/config.json" <<EOF
|
|
{
|
|
"port": "${port}",
|
|
"baudRate": ${baud_rate},
|
|
"shutdownWord": "${shutdown_word}"
|
|
}
|
|
EOF
|
|
info "已生成配置文件: ${INSTALL_DIR}/config.json"
|
|
}
|
|
|
|
# 生成 send_signal.sh
|
|
generate_send_signal() {
|
|
local port="$1"
|
|
local baud_rate="$2"
|
|
local shutdown_word="$3"
|
|
|
|
cat > "/usr/lib/systemd/system-shutdown/send_signal.sh" <<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 "/usr/lib/systemd/system-shutdown/send_signal.sh"
|
|
info "已安装关机钩子: /usr/lib/systemd/system-shutdown/send_signal.sh"
|
|
}
|
|
|
|
# 生成 systemd service
|
|
generate_service() {
|
|
cat > /etc/systemd/system/ttyshutdown.service <<EOF
|
|
[Unit]
|
|
Description=ttyshutdown
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=root
|
|
WorkingDirectory=${INSTALL_DIR}
|
|
ExecStart=${INSTALL_DIR}/shutdown
|
|
Restart=always
|
|
RestartSec=3
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
info "已生成 systemd 服务: /etc/systemd/system/ttyshutdown.service"
|
|
}
|
|
|
|
# 主安装流程
|
|
main() {
|
|
check_root
|
|
|
|
# 1. 选择串口
|
|
select_serial_port
|
|
info "已选择串口: $SELECTED_PORT"
|
|
|
|
# 2. 可选参数
|
|
local baud_rate=115200
|
|
local shutdown_word="SHUTDOWN"
|
|
echo ""
|
|
read -rp "波特率 [默认 115200]: " input_baud
|
|
if [ -n "$input_baud" ]; then
|
|
baud_rate="$input_baud"
|
|
fi
|
|
|
|
read -rp "关机指令 [默认 SHUTDOWN]: " input_word
|
|
if [ -n "$input_word" ]; then
|
|
shutdown_word="$input_word"
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${CYAN}=== 确认配置 ===${NC}"
|
|
echo " 串口设备: $SELECTED_PORT"
|
|
echo " 波特率: $baud_rate"
|
|
echo " 关机指令: $shutdown_word"
|
|
echo " 安装目录: $INSTALL_DIR"
|
|
echo ""
|
|
read -rp "确认安装? [Y/n]: " confirm
|
|
if [[ "$confirm" =~ ^[Nn] ]]; then
|
|
warn "已取消安装"
|
|
exit 0
|
|
fi
|
|
|
|
# 3. 检查二进制文件
|
|
if [ ! -f "${SCRIPT_DIR}/shutdown" ]; then
|
|
error "未找到预编译的 shutdown 二进制文件"
|
|
echo "请将 shutdown 二进制文件复制到 ${SCRIPT_DIR} 目录下"
|
|
exit 1
|
|
fi
|
|
|
|
# 4. 安装文件
|
|
mkdir -p "$INSTALL_DIR"
|
|
cp "${SCRIPT_DIR}/shutdown" "${INSTALL_DIR}/shutdown"
|
|
chmod +x "${INSTALL_DIR}/shutdown"
|
|
|
|
# 5. 生成配置
|
|
generate_config "$SELECTED_PORT" "$baud_rate" "$shutdown_word"
|
|
|
|
# 6. 安装关机钩子
|
|
mkdir -p /usr/lib/systemd/system-shutdown
|
|
generate_send_signal "$SELECTED_PORT" "$baud_rate" "$shutdown_word"
|
|
|
|
# 7. 生成并启用 systemd 服务
|
|
generate_service
|
|
systemctl daemon-reload
|
|
systemctl enable ttyshutdown.service
|
|
systemctl start ttyshutdown.service
|
|
|
|
echo ""
|
|
echo -e "${GREEN}========================================${NC}"
|
|
echo -e "${GREEN} 安装完成!${NC}"
|
|
echo -e "${GREEN}========================================${NC}"
|
|
echo -e " 服务状态: ${CYAN}systemctl status ttyshutdown${NC}"
|
|
echo -e " 查看日志: ${CYAN}journalctl -u ttyshutdown -f${NC}"
|
|
echo -e " 停止服务: ${CYAN}systemctl stop ttyshutdown${NC}"
|
|
echo -e " 卸载: ${CYAN}sudo bash ${SCRIPT_DIR}/uninstall.sh${NC}"
|
|
}
|
|
|
|
main
|