一、简介
太久没有写博客了,不是不想写,而是太忙了。最近我在使用 Avalonia UI 框架开发一个跨平台的应用程序,Avalonia 本身来说,还好了,社区很活跃,文档也很齐全。但是在统信系统中部署和打包 Avalonia 程序为安装包,我是从来都没有这样做过的。其实,在 Windows 平台下打包安装包,是很容易的,工具也是很多的,比如:Inno Setup,这个工具很好用,打包大文件效率也很高,唯一的缺点就是,使用门槛有点高,要写脚本。刚开始我还是不习惯的,不如可视化的界面操作简单。Inno Setup 的下载地址:Inno Setup 。
最近工作中,有一个需求,需要把 Avalonia 的程序打包成安装包,让顾客可以安装、卸载和使用,包括两个平台,一个是 Windows 平台,这个平台很快就搞定了。另外一个平台就是在 Linux 版本的【统信系统】中也要打包成安装包,我以前是从来没有这方面的经验,也困扰了我很久,头发都掉了一大把,终于经过2周的时间还是把打包的问题解决了。
在 Linux 版本的系统中打包安装包,有很多的坑,一个很重要的坑就是权限的问题。比如:登录用户的权限和打包、安装程序的权限不一致,可能就会导致桌面图标看不到,或者是文件夹浏览器看不到任何文件夹,但是用户就可以看到桌面有很多文件夹。如果你的安装包有需要管理员权限执行的,出现的问题更多,需要设置目录权限,启动脚本的权限,图标执行的权限。
二、操作过程
今天终于有时间了,把在【统信系统】中打包的脚本贴出来,这是一个很好的资源,也是经过我验证的,可以真正使用的。
这个脚本是最全的,可以生成桌面图标,开始菜单中的图标,设置启动脚本、目录的执行权限,卸载的时候,清楚桌面图标和开始菜单中的图标。
我在说一下目录结构:
|--PatrickLiuFileBrowser
| |--Linux64(avalonia 的程序)
| |----AIBroker(AI服务器--没有可以删除)
| |----HDServices(特殊服务--必须以管理员权限安装,没有可以删除)
| |---- Avalonia 的程序 so 文件和可执行文件
| |--usr(图标)
|--PatrickLiuFileBrowserSetup.sh(脚本文件)
1 #!/bin/bash
2
3 # 配置变量
4 PROJECT_NAME="PatrickLiuFileBrowser"
5 VERSION="2.5.4351"
6 ARCHITECTURE="amd64"
7 DEB_NAME="patrickLiuFileBrowser_${VERSION}_${ARCHITECTURE}.deb"
8 SOURCE_DIR="./PatrickLiuFileBrowser/Linux64"
9 STAGING_DIR="./staging_folder"
10
11 # 清理旧文件
12 echo "🧹 清理旧文件..."
13 rm -rf "${STAGING_DIR}"
14 rm -f ./*.deb
15
16 # 检查源目录是否存在
17 if [ ! -d "${SOURCE_DIR}" ]; then
18 echo "❌ 错误: 源目录不存在: ${SOURCE_DIR}"
19 exit 1
20 fi
21
22 # 检查主可执行文件
23 if [ ! -f "${SOURCE_DIR}/${PROJECT_NAME}" ]; then
24 echo "❌ 错误: 主可执行文件不存在"
25 exit 1
26 fi
27
28 # 检查服务文件
29 if [ ! -f "${SOURCE_DIR}/HDServices/hardDisk.service" ] || [ ! -f "${SOURCE_DIR}/HDServices/HardDiskInfoService" ]; then
30 echo "❌ 错误: 服务文件不存在"
31 exit 1
32 fi
33
34 # 创建目录结构
35 echo "📁 创建目录结构..."
36 mkdir -p "${STAGING_DIR}/DEBIAN"
37 mkdir -p "${STAGING_DIR}/usr/bin"
38 mkdir -p "${STAGING_DIR}/usr/lib/patrickLiuFileBrowser"
39 mkdir -p "${STAGING_DIR}/usr/lib/patrickLiuFileBrowser/HDServices"
40 mkdir -p "${STAGING_DIR}/usr/local/sbin"
41 mkdir -p "${STAGING_DIR}/etc/systemd/system"
42 mkdir -p "${STAGING_DIR}/usr/share/applications"
43 mkdir -p "${STAGING_DIR}/usr/share/pixmaps"
44 mkdir -p "${STAGING_DIR}/usr/share/icons"
45
46 # Debian control文件
47 echo "📝 创建控制文件..."
48 cat > "${STAGING_DIR}/DEBIAN/control" << EOF
49 Package: patrickLiuFileBrowser
50 Version: ${VERSION}
51 Section: utils
52 Priority: optional
53 Architecture: ${ARCHITECTURE}
54 Depends: libx11-6, libice6, libsm6, libfontconfig1, ca-certificates, tzdata, libc6, libgcc1 | libgcc-s1, libgssapi-krb5-2, libstdc++6, zlib1g, libssl1.0.0 | libssl1.0.2 | libssl1.1 | libssl3, libicu | libicu74 | libicu72 | libicu71 | libicu70 | libicu69 | libicu68 | libicu67 | libicu66 | libicu65 | libicu63 | libicu60 | libicu57 | libicu55 | libicu52
55 Maintainer: PatrickLiu <ll_efort@sina.com>
56 Description: AI智能文件管理器 - 跨平台AI文件浏览器
57 Copyright: 2022-2024 PatrickLiu
58 EOF
59
60 # 创建启动脚本 - 设置777权限
61 echo "📜 创建启动脚本..."
62 cat > "${STAGING_DIR}/usr/bin/patrickLiuFileBrowser" << 'EOF'
63 #!/bin/bash
64 APP_DIR="/usr/lib/patrickLiuFileBrowser"
65 cd "$APP_DIR" || exit 1
66 export LD_LIBRARY_PATH="$APP_DIR:$LD_LIBRARY_PATH"
67 export DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=0
68 exec "./PatrickLiuFileBrowser" "$@"
69 EOF
70 chmod 777 "${STAGING_DIR}/usr/bin/patrickLiuFileBrowser"
71
72 # 复制应用程序文件
73 echo "📦 复制应用程序文件中..."
74 if cp -r "${SOURCE_DIR}/"* "${STAGING_DIR}/usr/lib/patrickLiuFileBrowser/" 2>/dev/null; then
75 echo "✅ 应用程序文件复制完成"
76 else
77 echo "❌ 应用程序文件复制失败"
78 exit 1
79 fi
80
81 # 复制服务文件
82 echo "🔧 复制服务文件中..."
83 cp "${SOURCE_DIR}/HDServices/hardDisk.service" "${STAGING_DIR}/usr/lib/patrickLiuFileBrowser/HDServices/" 2>/dev/null
84 cp "${SOURCE_DIR}/HDServices/hardDisk.service" "${STAGING_DIR}/etc/systemd/system/" 2>/dev/null
85 cp "${SOURCE_DIR}/HDServices/HardDiskInfoService" "${STAGING_DIR}/usr/lib/patrickLiuFileBrowser/HDServices/" 2>/dev/null
86 cp "${SOURCE_DIR}/HDServices/HardDiskInfoService" "${STAGING_DIR}/usr/local/sbin/" 2>/dev/null
87 echo "✅ 服务文件复制完成"
88
89 # 设置文件权限
90 echo "🔒 设置文件权限中..."
91 chmod 777 "${STAGING_DIR}/usr/lib/patrickLiuFileBrowser/AIBroker" 2>/dev/null
92 chmod 777 "${STAGING_DIR}/usr/lib/patrickLiuFileBrowser/PatrickLiuFileBrowser" 2>/dev/null
93 chmod 777 "${STAGING_DIR}/usr/lib/patrickLiuFileBrowser/HDServices/HardDiskInfoService" 2>/dev/null
94 chmod 777 "${STAGING_DIR}/usr/local/sbin/HardDiskInfoService" 2>/dev/null
95 chmod 777 "${STAGING_DIR}/etc/systemd/system/hardDisk.service" 2>/dev/null
96 echo "✅ 文件权限设置完成"
97
98 # 创建维护脚本
99 echo "📜 创建维护脚本中..."
100
101 # preinst
102 cat > "${STAGING_DIR}/DEBIAN/preinst" << 'EOF'
103 #!/bin/bash
104 set -e
105 echo "停止旧版本的 AI智能文件管理器 服务..."
106 systemctl stop hd 2>/dev/null || true
107 exit 0
108 EOF
109
110 # postinst
111 cat > "${STAGING_DIR}/DEBIAN/postinst" << 'EOF'
112 #!/bin/bash
113 set -e
114 echo "配置 AI智能文件管理器 系统服务..."
115
116 # 复制服务文件
117 if [ ! -f "/etc/systemd/system/hardDisk.service" ] && [ -f "/usr/lib/patrickLiuFileBrowser/HDServices/hardDisk.service" ]; then
118 cp -f /usr/lib/patrickLiuFileBrowser/HDServices/hardDisk.service /etc/systemd/system/
119 fi
120
121 if [ ! -f "/usr/local/sbin/HardDiskInfoService" ] && [ -f "/usr/lib/patrickLiuFileBrowser/HDServices/HardDiskInfoService" ]; then
122 cp -f /usr/lib/patrickLiuFileBrowser/HDServices/HardDiskInfoService /usr/local/sbin/
123 fi
124
125 # 设置权限为777
126 chmod 777 /etc/systemd/system/hardDisk.service 2>/dev/null || true
127 chmod 777 /usr/local/sbin/HardDiskInfoService 2>/dev/null || true
128
129 # 为安装目录下的 AIBroker 和 HDServices 目录设置读写执行权限 (777)
130 echo "设置应用程序目录权限..."
131 APP_DIR="/usr/lib/patrickLiuFileBrowser"
132
133 if [ -d "$APP_DIR" ]; then
134 # 设置主目录权限为 777
135 chmod 777 "$APP_DIR" 2>/dev/null || true
136
137 # 特别设置 AIBroker 目录权限为 777 (rwxrwxrwx) - 所有者、组、其他用户都有读、写、执行权限
138 AIBROKER_DIR="$APP_DIR/AIBroker"
139 if [ -d "$AIBROKER_DIR" ]; then
140 echo "设置 AIBroker 目录权限为 777: $AIBROKER_DIR"
141 chmod 777 "$AIBROKER_DIR" 2>/dev/null || true
142 echo "✅ AIBroker 目录权限设置完成: $(ls -ld "$AIBROKER_DIR" 2>/dev/null | awk '{print $1}' || echo "未知")"
143 else
144 echo "⚠️ AIBroker 目录不存在: $AIBROKER_DIR"
145 fi
146
147 # 特别设置 HDServices 目录权限为 777 (rwxrwxrwx) - 所有者、组、其他用户都有读、写、执行权限
148 HDSERVICES_DIR="$APP_DIR/HDServices"
149 if [ -d "$HDSERVICES_DIR" ]; then
150 echo "设置 HDServices 目录权限为 777: $HDSERVICES_DIR"
151 chmod 777 "$HDSERVICES_DIR" 2>/dev/null || true
152 echo "✅ HDServices 目录权限设置完成: $(ls -ld "$HDSERVICES_DIR" 2>/dev/null | awk '{print $1}' || echo "未知")"
153 else
154 echo "⚠️ HDServices 目录不存在: $HDSERVICES_DIR"
155 fi
156
157 # 为所有可执行文件设置777权限
158 [ -f "$APP_DIR/PatrickLiuFileBrowser" ] && chmod 777 "$APP_DIR/PatrickLiuFileBrowser" 2>/dev/null || true
159 [ -f "$APP_DIR/AIBroker" ] && chmod 777 "$APP_DIR/AIBroker" 2>/dev/null || true
160 [ -f "$HDSERVICES_DIR/HardDiskInfoService" ] && chmod 777 "$HDSERVICES_DIR/HardDiskInfoService" 2>/dev/null || true
161
162 # 设置启动脚本权限为777
163 [ -f "/usr/bin/patrickLiuFileBrowser" ] && chmod 777 "/usr/bin/patrickLiuFileBrowser" 2>/dev/null || true
164
165 # 设置所有者
166 chown -R root:root "$APP_DIR" 2>/dev/null || true
167
168 echo "✅ 应用程序目录权限设置完成"
169 echo "📋 最终权限状态:"
170 echo " 📁 AIBroker 目录: $(ls -ld "$AIBROKER_DIR" 2>/dev/null | awk '{print $1 " " $3 ":" $4}' || echo "未知")"
171 echo " 📁 HDServices 目录: $(ls -ld "$HDSERVICES_DIR" 2>/dev/null | awk '{print $1 " " $3 ":" $4}' || echo "未知")"
172 echo " 📄 启动脚本: $(ls -ld "/usr/bin/patrickLiuFileBrowser" 2>/dev/null | awk '{print $1 " " $3 ":" $4}' || echo "未知")"
173 else
174 echo "⚠️ 应用程序目录不存在: $APP_DIR"
175 fi
176
177 # 重新加载 systemd
178 systemctl daemon-reload
179
180 # 启用服务
181 systemctl enable hd
182
183 # 启动服务
184 if systemctl start hd; then
185 echo "✅ hd 服务启动成功"
186 else
187 echo "⚠️ hd 服务启动失败,请检查: systemctl status hd"
188 fi
189
190 # 桌面快捷方式
191 if [ -n "$SUDO_USER" ]; then
192 USER_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6)
193 else
194 USER_HOME="$HOME"
195 fi
196
197 DESKTOP_FILE="/usr/share/applications/PatrickLiuFileBrowser.desktop"
198 USER_DESKTOP="$USER_HOME/Desktop/PatrickLiuFileBrowser.desktop"
199
200 if [ -d "$USER_HOME/Desktop" ] && [ -f "$DESKTOP_FILE" ]; then
201 cp "$DESKTOP_FILE" "$USER_DESKTOP"
202 chown "$SUDO_USER:$SUDO_USER" "$USER_DESKTOP" 2>/dev/null || true
203 chmod 777 "$USER_DESKTOP"
204 fi
205
206 # 更新桌面数据库
207 update-desktop-database /usr/share/applications 2>/dev/null || true
208 gtk-update-icon-cache /usr/share/icons/hicolor 2>/dev/null || true
209
210 echo "🎉 AI智能文件管理器 安装完成!"
211 exit 0
212 EOF
213
214 # prerm - 在卸载前执行
215 cat > "${STAGING_DIR}/DEBIAN/prerm" << 'EOF'
216 #!/bin/bash
217 set -e
218 ACTION="$1"
219 echo "执行 prerm 脚本,动作: $ACTION"
220
221 # 删除所有用户主目录下的 .ai-patrickLiu 目录及其内容
222 cleanup_user_data() {
223 echo "开始清理所有用户的 .ai-patrickLiu 数据目录..."
224
225 # 定义要删除的目录模式
226 AI_SEARCH_PATTERNS=(
227 ".ai-patrickLiu"
228 ".ai_patrickLiu"
229 "ai-patrickLiu"
230 "ai_patrickLiu"
231 )
232
233 # 查找所有可能的用户主目录
234 HOME_DIRS=()
235
236 # 从 /etc/passwd 获取所有用户的主目录
237 while IFS=: read -r username password uid gid gecos home shell; do
238 if [ -d "$home" ] && [[ "$home" == /home/* || "$home" == /root ]]; then
239 HOME_DIRS+=("$home")
240 fi
241 done < /etc/passwd
242
243 # 添加系统常见的主目录位置
244 [ -d "/home" ] && HOME_DIRS+=($(find /home -maxdepth 1 -type d 2>/dev/null))
245 [ -d "/root" ] && HOME_DIRS+=("/root")
246 [ -n "$HOME" ] && HOME_DIRS+=("$HOME")
247
248 # 去重
249 HOME_DIRS=($(printf "%s\n" "${HOME_DIRS[@]}" | sort -u))
250
251 # 遍历所有主目录并删除 .ai-patrickLiu 相关目录
252 for home_dir in "${HOME_DIRS[@]}"; do
253 if [ -d "$home_dir" ]; then
254 for pattern in "${AI_SEARCH_PATTERNS[@]}"; do
255 target_dir="$home_dir/$pattern"
256 if [ -d "$target_dir" ]; then
257 echo "准备删除用户数据目录: $target_dir"
258
259 # 第一步:递归设置目录权限为 777,确保可以删除
260 echo "设置目录权限为 777: $target_dir"
261 chmod -R 777 "$target_dir" 2>/dev/null || echo "⚠️ 权限设置失败,继续尝试删除"
262
263 # 第二步:更改所有者为当前用户(如果是root权限)
264 if [ "$(id -u)" -eq 0 ]; then
265 chown -R "$(id -u):$(id -g)" "$target_dir" 2>/dev/null || true
266 fi
267
268 # 第三步:使用 rm -rf 强制删除目录及其所有内容
269 echo "删除目录: $target_dir"
270 rm -rf "$target_dir" 2>/dev/null && echo "✅ 已删除目录: $target_dir" || echo "❌ 删除失败: $target_dir"
271
272 # 第四步:再次检查目录是否真的被删除
273 if [ -d "$target_dir" ]; then
274 echo "⚠️ 目录仍然存在,尝试使用更强制的方法删除: $target_dir"
275 # 尝试使用不同的方法
276 rm -rf -- "$target_dir" 2>/dev/null || true
277
278 # 如果还是存在,尝试使用更激进的方法
279 if [ -d "$target_dir" ]; then
280 echo "🚨 使用强制删除命令: $target_dir"
281 # 使用 find 和 rm 组合强制删除
282 find "$target_dir" -type f -exec rm -f {} \; 2>/dev/null || true
283 find "$target_dir" -type d -exec rm -rf {} \; 2>/dev/null || true
284 rm -rf "$target_dir" 2>/dev/null || true
285 fi
286 else
287 echo "✅ 目录已成功删除: $target_dir"
288 fi
289 fi
290 done
291
292 # 删除桌面快捷方式
293 desktop_file="$home_dir/Desktop/PatrickLiuFileBrowser.desktop"
294 if [ -f "$desktop_file" ]; then
295 echo "删除桌面文件: $desktop_file"
296 chmod 777 "$desktop_file" 2>/dev/null || true
297 rm -f "$desktop_file" 2>/dev/null && echo "✅ 已删除: $desktop_file" || echo "❌ 删除失败: $desktop_file"
298 fi
299 fi
300 done
301
302 echo "✅ 用户数据清理完成"
303 }
304
305 case "$ACTION" in
306 "remove"|"purge")
307 echo "卸载操作 - 停止服务并清理用户数据..."
308 # 停止服务
309 systemctl stop hd 2>/dev/null || true
310 systemctl disable hd 2>/dev/null || true
311
312 # 清理用户数据
313 cleanup_user_data
314 ;;
315 "upgrade"|"deconfigure")
316 echo "升级或重新配置操作 - 停止服务..."
317 systemctl stop hd 2>/dev/null || true
318 ;;
319 *)
320 echo "未知操作: $ACTION"
321 ;;
322 esac
323
324 exit 0
325 EOF
326
327 # postrm - 在卸载后执行
328 cat > "${STAGING_DIR}/DEBIAN/postrm" << 'EOF'
329 #!/bin/bash
330 set -e
331
332 ACTION="$1"
333 echo "执行 postrm 脚本,动作: $ACTION"
334
335 # 清理系统文件的函数
336 cleanup_system_files() {
337 echo "开始清理系统文件..."
338
339 # 删除系统服务文件
340 if [ -f "/etc/systemd/system/hardDisk.service" ]; then
341 echo "删除系统服务文件: /etc/systemd/system/hardDisk.service"
342 rm -f /etc/systemd/system/hardDisk.service
343 fi
344
345 # 删除服务程序
346 if [ -f "/usr/local/sbin/HardDiskInfoService" ]; then
347 echo "删除服务程序: /usr/local/sbin/HardDiskInfoService"
348 rm -f /usr/local/sbin/HardDiskInfoService
349 fi
350
351 # 删除应用程序目录
352 if [ -d "/usr/lib/patrickLiuFileBrowser" ]; then
353 echo "删除应用程序目录: /usr/lib/patrickLiuFileBrowser"
354 rm -rf /usr/lib/patrickLiuFileBrowser
355 fi
356
357 # 删除启动脚本
358 if [ -f "/usr/bin/patrickLiuFileBrowser" ]; then
359 echo "删除启动脚本: /usr/bin/patrickLiuFileBrowser"
360 rm -f /usr/bin/patrickLiuFileBrowser
361 fi
362
363 # 删除桌面文件
364 if [ -f "/usr/share/applications/PatrickLiuFileBrowser.desktop" ]; then
365 echo "删除桌面文件: /usr/share/applications/PatrickLiuFileBrowser.desktop"
366 rm -f /usr/share/applications/PatrickLiuFileBrowser.desktop
367 fi
368
369 # 删除图标文件
370 if [ -f "/usr/share/pixmaps/patrickLiuFileBrowser.png" ]; then
371 echo "删除图标文件: /usr/share/pixmaps/patrickLiuFileBrowser.png"
372 rm -f /usr/share/pixmaps/patrickLiuFileBrowser.png
373 fi
374
375 if [ -f "/usr/share/icons/patrickLiuFileBrowser.ico" ]; then
376 echo "删除图标文件: /usr/share/icons/patrickLiuFileBrowser.ico"
377 rm -f /usr/share/icons/patrickLiuFileBrowser.ico
378 fi
379
380 echo "✅ 系统文件清理完成"
381 }
382
383 # 再次清理用户数据的函数(确保彻底清理)
384 cleanup_user_data_again() {
385 echo "再次确认清理所有用户数据..."
386
387 # 使用 find 命令递归查找并删除所有 .ai-patrickLiu 目录
388 echo "使用 find 命令搜索所有 .ai-patrickLiu 目录..."
389 find /home /root -name ".ai-patrickLiu" -type d 2>/dev/null | while read ai_patrickLiu_dir; do
390 if [ -d "$ai_patrickLiu_dir" ]; then
391 echo "找到目录: $ai_patrickLiu_dir"
392
393 # 第一步:设置完整权限
394 echo "设置权限为 777: $ai_patrickLiu_dir"
395 chmod -R 777 "$ai_patrickLiu_dir" 2>/dev/null || echo "⚠️ 权限设置失败,继续尝试删除"
396
397 # 第二步:强制删除
398 echo "强制删除目录: $ai_patrickLiu_dir"
399 rm -rf "$ai_patrickLiu_dir" 2>/dev/null && echo "✅ 已删除目录: $ai_patrickLiu_dir" || echo "❌ 删除失败: $ai_patrickLiu_dir"
400
401 # 第三步:验证删除
402 if [ -d "$ai_patrickLiu_dir" ]; then
403 echo "🚨 目录仍然存在,使用终极删除方法: $ai_patrickLiu_dir"
404 # 终极方法:使用更激进的删除
405 find "$ai_patrickLiu_dir" -type f -exec chmod 777 {} \; -exec rm -f {} \; 2>/dev/null || true
406 find "$ai_patrickLiu_dir" -type d -exec chmod 777 {} \; -exec rmdir {} \; 2>/dev/null || true
407 rm -rf "$ai_patrickLiu_dir" 2>/dev/null || true
408
409 if [ ! -d "$ai_patrickLiu_dir" ]; then
410 echo "✅ 最终删除成功: $ai_patrickLiu_dir"
411 else
412 echo "❌ 无法删除目录: $ai_patrickLiu_dir"
413 fi
414 fi
415 fi
416 done
417
418 # 使用 find 命令查找其他可能的变体
419 find /home /root -name ".ai_patrickLiu" -type d 2>/dev/null | while read ai_patrickLiu_dir; do
420 if [ -d "$ai_patrickLiu_dir" ]; then
421 echo "找到并删除: $ai_patrickLiu_dir"
422 chmod -R 777 "$ai_patrickLiu_dir" 2>/dev/null || true
423 rm -rf "$ai_patrickLiu_dir" 2>/dev/null && echo "✅ 已删除目录: $ai_patrickLiu_dir" || echo "⚠️ 删除失败: $ai_patrickLiu_dir"
424 fi
425 done
426
427 # 手动检查常见位置
428 echo "手动检查常见用户目录..."
429
430 # 检查 /home 下的所有用户
431 for user_dir in /home/*; do
432 if [ -d "$user_dir" ]; then
433 ai_patrickLiu_dir="$user_dir/.ai-patrickLiu"
434 if [ -d "$ai_patrickLiu_dir" ]; then
435 echo "手动删除: $ai_patrickLiu_dir"
436 chmod -R 777 "$ai_patrickLiu_dir" 2>/dev/null || true
437 rm -rf "$ai_patrickLiu_dir" 2>/dev/null && echo "✅ 已删除: $ai_patrickLiu_dir" || echo "⚠️ 删除失败: $ai_patrickLiu_dir"
438 fi
439 fi
440 done
441
442 # 检查 root 用户
443 if [ -d "/root/.ai-patrickLiu" ]; then
444 echo "删除 root 用户数据目录: /root/.ai-patrickLiu"
445 chmod -R 777 "/root/.ai-patrickLiu" 2>/dev/null || true
446 rm -rf "/root/.ai-patrickLiu" 2>/dev/null && echo "✅ 已删除: /root/.ai-patrickLiu" || echo "⚠️ 删除失败: /root/.ai-patrickLiu"
447 fi
448
449 # 检查当前用户
450 if [ -n "$HOME" ] && [ -d "$HOME/.ai-patrickLiu" ]; then
451 echo "删除当前用户数据目录: $HOME/.ai-patrickLiu"
452 chmod -R 777 "$HOME/.ai-patrickLiu" 2>/dev/null || true
453 rm -rf "$HOME/.ai-patrickLiu" 2>/dev/null && echo "✅ 已删除: $HOME/.ai-patrickLiu" || echo "⚠️ 删除失败: $HOME/.ai-patrickLiu"
454 fi
455
456 # 删除所有桌面快捷方式
457 find /home /root -name "PatrickLiuFileBrowser.desktop" -path "*/Desktop/*" -type f 2>/dev/null | while read desktop_file; do
458 echo "删除桌面文件: $desktop_file"
459 chmod 777 "$desktop_file" 2>/dev/null || true
460 rm -f "$desktop_file" 2>/dev/null && echo "✅ 已删除: $desktop_file" || echo "⚠️ 删除失败: $desktop_file"
461 done
462
463 echo "✅ 用户数据二次清理完成"
464 }
465
466 case "$ACTION" in
467 "remove"|"purge")
468 echo "卸载操作 - 彻底清理系统文件和用户数据..."
469
470 # 清理系统文件
471 cleanup_system_files
472
473 # 再次清理用户数据确保彻底删除
474 cleanup_user_data_again
475
476 # 重新加载 systemd
477 systemctl daemon-reload 2>/dev/null || true
478 systemctl reset-failed 2>/dev/null || true
479 ;;
480 "upgrade"|"failed-upgrade"|"abort-install"|"abort-upgrade"|"disappear")
481 echo "升级或安装中止操作,跳过系统文件清理"
482 ;;
483 *)
484 echo "未知操作: $ACTION"
485 ;;
486 esac
487
488 # 更新桌面数据库和图标缓存
489 if [ "$ACTION" = "remove" ] || [ "$ACTION" = "purge" ] || [ "$ACTION" = "upgrade" ]; then
490 echo "更新桌面数据库..."
491 update-desktop-database /usr/share/applications 2>/dev/null || true
492 echo "更新图标缓存..."
493 gtk-update-icon-cache /usr/share/icons/hicolor 2>/dev/null || true
494 fi
495
496 echo "postrm 脚本执行完成"
497 exit 0
498 EOF
499
500 chmod 755 "${STAGING_DIR}/DEBIAN/preinst" \
501 "${STAGING_DIR}/DEBIAN/postinst" \
502 "${STAGING_DIR}/DEBIAN/prerm" \
503 "${STAGING_DIR}/DEBIAN/postrm"
504
505 echo "✅ 维护脚本创建完成"
506
507 # 创建桌面文件 - 只修改显示名称为中文,保持文件名和图标路径不变
508 echo "🖥️ 创建桌面文件中..."
509 cat > "${STAGING_DIR}/usr/share/applications/PatrickLiuFileBrowser.desktop" << EOF
510 [Desktop Entry]
511 Name=AI智能文件管理器
512 Comment=AI智能文件管理器 - 智能文件浏览器
513 Icon=/usr/share/icons/patrickLiuFileBrowser.ico
514 Exec=/usr/bin/patrickLiuFileBrowser
515 StartupWMClass=PatrickLiuFileBrowser
516 Terminal=false
517 Type=Application
518 Categories=Utility;Application;
519 StartupNotify=true
520 GenericName=AI智能文件管理器
521 Keywords=AI; files browser; ai files browser; 华方; AI搜索
522 EOF
523
524 # 复制图标文件 - 按之前逻辑处理
525 echo "🎨 复制图标文件中..."
526 [ -f "./PatrickLiuFileBrowser/usr/share/pixmaps/patrickLiuFileBrowser.png" ] && \
527 cp "./PatrickLiuFileBrowser/usr/share/pixmaps/patrickLiuFileBrowser.png" "${STAGING_DIR}/usr/share/pixmaps/" 2>/dev/null && \
528 echo "✅ PNG图标复制完成"
529
530 [ -f "./PatrickLiuFileBrowser/usr/share/icons/patrickLiuFileBrowser.ico" ] && \
531 cp "./PatrickLiuFileBrowser/usr/share/icons/patrickLiuFileBrowser.ico" "${STAGING_DIR}/usr/share/icons/" 2>/dev/null && \
532 echo "✅ ICO图标复制完成"
533
534 # 设置图标权限
535 find "${STAGING_DIR}/usr/share/icons" "${STAGING_DIR}/usr/share/pixmaps" -type f 2>/dev/null | while read icon_file; do
536 chmod 644 "$icon_file" 2>/dev/null || true
537 done
538
539 # 计算安装大小
540 echo "📊 计算安装大小中..."
541 INSTALLED_SIZE=$(du -sk "${STAGING_DIR}/usr" 2>/dev/null | cut -f1 || echo "0")
542 echo "Installed-Size: $INSTALLED_SIZE" >> "${STAGING_DIR}/DEBIAN/control"
543
544 # 使用可靠的打包方法
545 echo "🏗️ 开始构建 DEB 包..."
546
547 # 方法1: 使用fakeroot和dpkg-deb,禁用压缩
548 if command -v fakeroot >/dev/null 2>&1 && command -v dpkg-deb >/dev/null 2>&1; then
549 echo "使用方法1: fakeroot + dpkg-deb (无压缩)..."
550 if fakeroot dpkg-deb -Znone -b "${STAGING_DIR}" "${DEB_NAME}" 2>/dev/null; then
551 echo "✅ DEB 包构建成功: ${DEB_NAME}"
552 else
553 echo "❌ 方法1失败"
554 exit 1
555 fi
556 else
557 echo "❌ 缺少必要的打包工具"
558 exit 1
559 fi
560
561 # 验证包
562 if [ -f "${DEB_NAME}" ]; then
563 echo "📏 包大小: $(du -h "${DEB_NAME}" | cut -f1)"
564 echo ""
565 echo "🎉 打包完成!"
566 echo ""
567 echo "📦 安装命令:"
568 echo "sudo dpkg -i ${DEB_NAME}"
569 echo "# 如果依赖有问题,运行: sudo apt-get install -f"
570 echo ""
571 echo "🔧 服务管理命令:"
572 echo "sudo systemctl status hd # 查看服务状态"
573 echo "sudo systemctl start hd # 启动服务"
574 echo "sudo systemctl stop hd # 停止服务"
575 echo "sudo systemctl restart hd # 重启服务"
576 echo "sudo journalctl -u hd -f # 查看服务日志"
577 echo ""
578 echo "🖥️ 桌面图标:"
579 echo "- 安装后会在应用程序菜单中显示 'AI智能文件管理器'"
580 echo "- 会自动创建桌面快捷方式"
581 echo "- 如果图标不显示,请尝试注销重新登录"
582 echo ""
583 echo "🗑️ 卸载命令:"
584 echo "sudo apt remove patrickLiuFileBrowser # 卸载软件(会彻底删除所有文件)"
585 echo "sudo apt purge patrickLiuFileBrowser # 完全卸载(同上,现在remove和purge效果一样)"
586 echo "sudo apt autoremove # 清理未使用的依赖"
587 echo ""
588 echo "💡 重要提示:"
589 echo "- 卸载时会彻底删除以下内容:"
590 echo " ✓ 所有系统文件 (/usr/lib/patrickLiuFileBrowser, /etc/systemd/system/hardDisk.service 等)"
591 echo " ✓ 所有用户主目录下的 .ai-patrickLiu 目录和内容(包括目录本身)"
592 echo " ✓ 所有桌面快捷方式"
593 echo "- 在删除前会自动设置目录权限为 777 确保可以删除"
594 echo "- 卸载操作不可逆,请备份重要数据"
595 else
596 echo "❌ DEB 包文件未生成"
597 exit 1
598 fi
大家可以根据自己的具体需求,修改该文件,就可以直接使用。把不需要删掉就可以了,当然相关的配置节也要删掉。我这个版本在安装的时候回先安装服务,启动服务,配置为随操作系统自启动,当卸载的时候也会卸载掉相应的服务,删除产生的隐藏文件夹的数据。
三、总结好了,这个项目对我的收获还是很大的,我不光在 Avalonia 技术上取得突破的进展,无论是在框架上还是在技术细节上都有更深的学习。另外一个收获就是这个打包的过程,虽然这个过程还是很熬人的,问题也是层出不穷,最终都解决了。这个脚本不是一次写出来的,是经过多次迭代和完善,才形成这个完整的脚本。好了,今天就写到这里。不忘初心,继续努力。