Skip to content

Commit 18e7133

Browse files
authored
Merge pull request #674 from lyjjl/main
fix(script): 修复了选择模式和清理时Ctrl+C导致的崩溃(顺便让代码短了点
2 parents 181741f + 8aa6e3b commit 18e7133

File tree

1 file changed

+58
-92
lines changed

1 file changed

+58
-92
lines changed

script/start-linux.sh

Lines changed: 58 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,27 @@ export PATH=$PATH:/usr/bin:/usr/local/bin
55

66
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
77

8+
# 状态变量
89
CLEANING=0
910
PMHQ_PID=""
1011
USE_XVFB=0
1112
DISTRO=""
13+
PMHQ_BIN="$SCRIPT_DIR/llbot/pmhq"
1214

1315
log() { echo -e "${GREEN}>>> $1${NC}"; }
1416
warn() { echo -e "${YELLOW}>>> $1${NC}"; }
1517
error() { echo -e "${RED}错误: $1${NC}"; exit 1; }
1618

1719
check_sudo() {
1820
log "验证 Sudo 权限..."
19-
if ! sudo -v; then
20-
error "Sudo 验证失败或被取消,脚本终止。"
21-
fi
21+
sudo -v || error "Sudo 验证失败或被取消,脚本终止。"
2222
}
2323

2424
cleanup() {
2525
# 防止用户对 Ctrl+C 突然产生某种异样的迷恋然后狂按 Ctrl+C
2626
[ "$CLEANING" -eq 1 ] && return
2727
CLEANING=1
28+
trap '' SIGINT SIGTERM # 屏蔽后续 Ctrl+C,防止崩溃
2829

2930
# 防止日志挡交互
3031
if [ -n "$PMHQ_PID" ] && kill -0 "$PMHQ_PID" 2>/dev/null; then
@@ -38,9 +39,17 @@ cleanup() {
3839
local choice=""
3940

4041
if [ -n "$PMHQ_PID" ]; then
41-
if read -t 5 -n 1 -r -p "是否关闭 QQ 及相关进程? [Y/n] (5秒后默认关闭): " choice < /dev/tty; then
42-
echo ""
43-
else
42+
local T_COUNT=5
43+
while [ $T_COUNT -gt 0 ]; do
44+
printf "\r是否关闭 PMHQ 及 QQ 相关进程? [Y/n] (${T_COUNT}秒后默认关闭): "
45+
if read -t 1 -n 1 choice < /dev/tty; then
46+
echo ""
47+
break
48+
fi
49+
((T_COUNT--))
50+
done
51+
52+
if [ $T_COUNT -eq 0 ]; then
4453
echo ""
4554
log "等待超时,执行默认关闭操作。"
4655
fi
@@ -52,25 +61,21 @@ cleanup() {
5261

5362
if [ $kill_qq -eq 1 ]; then
5463
warn "正在停止服务..."
55-
56-
kill -CONT -"$PMHQ_PID" 2>/dev/null
57-
58-
kill -TERM -"$PMHQ_PID" 2>/dev/null
64+
[ -n "$PMHQ_PID" ] && kill -CONT -"$PMHQ_PID" 2>/dev/null
65+
[ -n "$PMHQ_PID" ] && kill -TERM -"$PMHQ_PID" 2>/dev/null
5966
pkill -15 -f "$PMHQ_BIN" 2>/dev/null
6067
pkill -15 -f "/opt/QQ/qq" 2>/dev/null
6168

6269
local wait_count=0
63-
64-
while kill -0 "$PMHQ_PID" 2>/dev/null || \
65-
pgrep -f "$PMHQ_BIN" > /dev/null || \
66-
pgrep -f "/opt/QQ/qq" > /dev/null; do
70+
while kill -0 "$PMHQ_PID" 2>/dev/null || pgrep -f "$PMHQ_BIN" > /dev/null || pgrep -f "/opt/QQ/qq" > /dev/null; do
6771
sleep 0.5
6872
((wait_count++))
6973
if [ $wait_count -ge 6 ]; then
7074
warn "检测到残留进程,执行强制清理..."
7175
# 气死我了,总有点关不掉进程的毛病,累了,跟我 pkill -9 说去吧
76+
# 可能会误伤别的 QQ 的进程罢
7277
# 期待大手子修复
73-
kill -KILL -"$PMHQ_PID" 2>/dev/null
78+
[ -n "$PMHQ_PID" ] && kill -9 -"$PMHQ_PID" 2>/dev/null
7479
pkill -9 -f "$PMHQ_BIN" 2>/dev/null
7580
pkill -9 -f "/opt/QQ/qq" 2>/dev/null
7681
break
@@ -79,16 +84,13 @@ cleanup() {
7984

8085
# 环境清理
8186
if [ "$DISTRO" != "arch" ] && [ "$USE_XVFB" -eq 0 ]; then
82-
if command -v xhost &> /dev/null; then
83-
xhost -local:$(whoami) > /dev/null 2>&1
84-
fi
87+
command -v xhost &> /dev/null && xhost -local:$(whoami) > /dev/null 2>&1
8588
fi
8689
log "所有进程已清理完毕。"
8790
else
8891
# 选择不关闭时必须恢复进程运行
89-
kill -CONT -"$PMHQ_PID" 2>/dev/null
92+
[ -n "$PMHQ_PID" ] && kill -CONT -"$PMHQ_PID" 2>/dev/null
9093
log "已恢复后台进程运行 (PGID: $PMHQ_PID)"
91-
warn "注意:它们已脱离脚本控制,后续请手动管理"
9294
fi
9395

9496
exit 0
@@ -97,7 +99,8 @@ cleanup() {
9799
trap cleanup SIGINT SIGTERM
98100

99101
confirm() {
100-
read -n 1 -s -r -p "$1 (Y/n) " key
102+
local key=""
103+
read -n 1 -s -r -p "$1 (Y/n) " key < /dev/tty
101104
echo ""
102105
[[ "$key" == "Y" || "$key" == "y" || "$key" == "" ]]
103106
}
@@ -110,17 +113,18 @@ find_port() {
110113
return 0
111114
fi
112115
# 回退方案:扫描可用端口
113-
local port=$1
114-
while [ $port -lt 65535 ]; do
115-
if ! ss -tuln 2>/dev/null | grep -q ":$port " && ! netstat -tuln 2>/dev/null | grep -q ":$port "; then
116-
echo $port
116+
local p=$1
117+
while [ $p -lt 65535 ]; do
118+
if ! ss -tuln 2>/dev/null | grep -q ":$p " && ! netstat -tuln 2>/dev/null | grep -q ":$p "; then
119+
echo $p
117120
return 0
118121
fi
119-
((port++))
122+
((p++))
120123
done
121124
return 1
122125
}
123126

127+
# 环境检查
124128
if command -v pacman &> /dev/null; then
125129
DISTRO="arch"
126130
elif command -v apt &> /dev/null; then
@@ -138,12 +142,12 @@ install_arch() {
138142
if [ ! -f "/opt/QQ/qq" ] && confirm "未检测到 QQ,是否通过 AUR 安装?"; then
139143
if ! command -v yay &> /dev/null; then
140144
warn "未检测到 yay,尝试安装..."
141-
if ! sudo pacman -S --needed --noconfirm yay 2>/dev/null; then
142-
warn "pacman 安装 yay 失败,切换源码编译..."
143-
rm -rf /tmp/yay_install && git clone https://aur.archlinux.org/yay.git /tmp/yay_install
144-
(cd /tmp/yay_install && makepkg -si --noconfirm) || error "yay 编译失败"
145-
rm -rf /tmp/yay_install
146-
fi
145+
sudo pacman -S --needed --noconfirm yay || {
146+
local TMP_DIR="/tmp/yay_install"
147+
rm -rf "$TMP_DIR" && git clone https://aur.archlinux.org/yay.git "$TMP_DIR"
148+
(cd "$TMP_DIR" && makepkg -si --noconfirm) || { rm -rf "$TMP_DIR"; error "yay 编译失败"; }
149+
rm -rf "$TMP_DIR"
150+
}
147151
fi
148152
yay -S --noconfirm linuxqq || error "LinuxQQ 安装失败"
149153
fi
@@ -152,53 +156,29 @@ install_arch() {
152156
install_debian() {
153157
check_sudo
154158
local MACHINE=$(uname -m)
155-
local ARCH=""
156159
case "$MACHINE" in
157-
x86_64) ARCH="amd64" ;;
158-
aarch64) ARCH="arm64" ;;
159-
*) error "不支持的架构: $MACHINE" ;;
160+
x86_64) ARCH="amd64" ;;
161+
aarch64) ARCH="arm64" ;;
162+
*) error "不支持的架构: $MACHINE" ;;
160163
esac
161164

162165
if [ ! -f "/opt/QQ/qq" ] && confirm "未检测到 QQ,是否安装?"; then
163-
log "下载并安装 QQ ($ARCH)..."
164-
sudo apt-get update && sudo apt-get install -y wget || error "apt update 或 wget 安装失败"
165-
166+
sudo apt-get update && sudo apt-get install -y wget || error "基础工具安装失败"
166167
local DEB="/tmp/qq.deb"
167-
wget -O "$DEB" "https://dldir1v6.qq.com/qqfile/qq/QQNT/ab90fdfa/linuxqq_3.2.20-40768_$ARCH.deb" || error "QQ 安装包下载失败"
168-
168+
wget -O "$DEB" "https://dldir1v6.qq.com/qqfile/qq/QQNT/ab90fdfa/linuxqq_3.2.20-40768_$ARCH.deb" || error "下载失败"
169169
local LIB_SND="libasound2"
170-
if apt-cache show libasound2t64 &>/dev/null; then
171-
LIB_SND="libasound2t64"
172-
fi
173-
log "使用 ALSA 库包名: $LIB_SND"
174-
175-
sudo apt install -y "$DEB" x11-utils libgtk-3-0 libxcb-xinerama0 libgl1-mesa-dri libnotify4 libnss3 xdg-utils libsecret-1-0 libappindicator3-1 libgbm1 $LIB_SND fonts-noto-cjk libxss1 || error "QQ 依赖安装失败"
170+
apt-cache show libasound2t64 &>/dev/null && LIB_SND="libasound2t64"
171+
sudo apt install -y "$DEB" x11-utils libgtk-3-0 libxcb-xinerama0 libgl1-mesa-dri libnotify4 libnss3 xdg-utils libsecret-1-0 libappindicator3-1 libgbm1 $LIB_SND fonts-noto-cjk libxss1 || error "依赖安装失败"
176172
rm -f "$DEB"
177173
fi
178-
179-
# 检查其他工具
180-
local missing_pkgs=""
181-
for pkg in ffmpeg xvfb; do
182-
if ! command -v $pkg &> /dev/null; then
183-
missing_pkgs="$missing_pkgs $pkg"
184-
fi
185-
done
186-
187-
if [ -n "$missing_pkgs" ]; then
188-
log "安装缺失工具: $missing_pkgs"
189-
sudo apt-get install -y $missing_pkgs || error "工具安装失败"
190-
fi
174+
sudo apt-get install -y ffmpeg xvfb || error "工具安装失败"
191175
}
192176

193177
# 执行安装
194-
if [ "$DISTRO" == "arch" ]; then
195-
install_arch
196-
else
197-
install_debian
198-
fi
199-
200-
chmod +x "$SCRIPT_DIR/llbot/node" "$SCRIPT_DIR/llbot/pmhq" 2>/dev/null
178+
[ "$DISTRO" == "arch" ] && install_arch || install_debian
201179

180+
# 配置权限
181+
chmod +x "$SCRIPT_DIR/llbot/node" "$PMHQ_BIN" 2>/dev/null
202182
sudo chown -R $(whoami):$(whoami) "$SCRIPT_DIR/llbot" 2>/dev/null
203183

204184
PORT=$(find_port 13000)
@@ -207,75 +187,61 @@ log "分配端口: $PORT"
207187

208188
echo "------------------------------------------------"
209189
echo "1) GUI 模式 (有界面)"
210-
echo "2) Shell 模式 (无界面/Headless,默认)"
190+
echo "2) Shell 模式 (无界面)"
211191
echo "------------------------------------------------"
212192

213193
MODE_CHOICE=""
214194
TIMEOUT=5
215195
while [ $TIMEOUT -gt 0 ]; do
216196
printf "\r请选择 [1/2] (${TIMEOUT}秒后自动选择 Shell): "
217-
if read -t 1 -n 1 MODE_CHOICE; then
197+
# 使用 tty 确保 read 不被管道干扰
198+
if read -t 1 -n 1 MODE_CHOICE < /dev/tty; then
218199
echo ""
219200
break
220201
fi
221202
((TIMEOUT--))
222203
done
223-
[ $TIMEOUT -eq 0 ] && echo "" && log "超时,自动选择 Shell 模式"
204+
[ -z "$MODE_CHOICE" ] && { echo ""; log "超时,自动选择 Shell 模式"; }
224205

225206
MODE_CHOICE=${MODE_CHOICE:-2}
226207
USE_XVFB=$([ "$MODE_CHOICE" == "2" ] && echo 1 || echo 0)
227208

209+
# X11/Wayland 变量处理
228210
if [ $USE_XVFB -eq 0 ]; then
229211
if command -v xauth &> /dev/null; then
230212
export XAUTHORITY=${XAUTHORITY:-$HOME/.Xauthority}
231213
else
232-
warn "未检测到 xauth,使用临时 xhost 授权"
233214
xhost +local:$(whoami) > /dev/null 2>&1
234215
fi
235216
fi
236217

237-
IM_ENV=""
218+
IM_ENV="XMODIFIERS=@im=fcitx"
238219
EXTRA_FLAGS=""
239-
240220
if [[ "$XDG_SESSION_TYPE" == "wayland" || -n "$WAYLAND_DISPLAY" ]]; then
241-
log "检测到 Wayland 环境"
242-
IM_ENV="XMODIFIERS=@im=fcitx"
243221
EXTRA_FLAGS="--enable-features=UseOzonePlatform --ozone-platform=wayland --enable-wayland-ime"
244222
else
245-
log "检测到 X11 环境"
246-
IM_ENV="GTK_IM_MODULE=fcitx QT_IM_MODULE=fcitx XMODIFIERS=@im=fcitx SDL_IM_MODULE=fcitx GLFW_IM_MODULE=ibus"
223+
IM_ENV="GTK_IM_MODULE=fcitx QT_IM_MODULE=fcitx $IM_ENV SDL_IM_MODULE=fcitx GLFW_IM_MODULE=ibus"
247224
fi
248225

249-
NODE_BIN="$SCRIPT_DIR/llbot/node"
250-
LLBOT_JS="$SCRIPT_DIR/llbot/llbot.js"
251-
PMHQ_BIN="$SCRIPT_DIR/llbot/pmhq"
252-
253226
run_llbot() {
254227
set -m
255-
256228
if [ "$DISTRO" == "arch" ]; then
257229
export LD_PRELOAD="/usr/lib/libstdc++.so.6:/usr/lib/libgcc_s.so.1"
258230
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
259231
fi
260232

261-
local sub_cmd="$NODE_BIN --enable-source-maps $LLBOT_JS -- --pmhq-port=$PORT --no-sandbox $EXTRA_FLAGS"
262-
263-
log "正在启动 LLBot... (模式: $([ $USE_XVFB -eq 1 ] && echo "Headless" || echo "GUI"))"
264-
log "按 Ctrl+C 可停止运行"
233+
local sub_cmd="$SCRIPT_DIR/llbot/node --enable-source-maps $SCRIPT_DIR/llbot/llbot.js -- --pmhq-port=$PORT --no-sandbox $EXTRA_FLAGS"
234+
log "启动模式: $([ $USE_XVFB -eq 1 ] && echo "Headless" || echo "GUI")"
265235

266236
if [ $USE_XVFB -eq 1 ]; then
267237
env $IM_ENV xvfb-run -a "$PMHQ_BIN" --port="$PORT" --sub-cmd="$sub_cmd" &
268238
else
269-
if [ "$DISTRO" != "arch" ]; then
270-
xhost +local:$(whoami) > /dev/null 2>&1
271-
fi
239+
[ "$DISTRO" != "arch" ] && xhost +local:$(whoami) > /dev/null 2>&1
272240
env $IM_ENV "$PMHQ_BIN" --port="$PORT" --sub-cmd="$sub_cmd" &
273241
fi
274242

275243
PMHQ_PID=$!
276-
277-
# 阻塞等待进程结束
278-
wait "$PMHQ_PID" || true
244+
wait "$PMHQ_PID" 2>/dev/null
279245
}
280246

281247
run_llbot

0 commit comments

Comments
 (0)