install.sh 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. #!/bin/bash
  2. # OLED中文系统监控器安装脚本 - 终极修复版 v2.0(已修复)
  3. # 说明:此脚本基于用户原始脚本全面修复:
  4. # - 添加 start_step(步骤计数)并自动递增 CURRENT_STEP
  5. # - 修复 show_progress(百分比、填充条、转轮、颜色、行尾残影)
  6. # - 保留原有流程、日志、I2C 检测、systemd 服务创建等逻辑
  7. # - 在脚本中加入中文注释,便于阅读与维护
  8. # ---------------------------
  9. # 颜色定义(ANSI)—— 中文注释
  10. # ---------------------------
  11. RED='\033[0;31m'
  12. GREEN='\033[0;32m'
  13. YELLOW='\033[1;33m'
  14. BLUE='\033[0;34m'
  15. MAGENTA='\033[0;35m'
  16. CYAN='\033[0;36m'
  17. NC='\033[0m' # No Color
  18. # ---------------------------
  19. # 全局变量 - 终极修复版配置
  20. # ---------------------------
  21. TOTAL_STEPS=18
  22. CURRENT_STEP=0
  23. INSTALL_DIR="/opt/oled_monitor_final" # 使用新目录避免冲突
  24. SYSTEM_USER="root"
  25. SYSTEM_GROUP="root"
  26. MAIN_PROGRAM="oled_system_monitor_final.py" # 新的程序文件名
  27. SERVICE_NAME="oled-monitor-final.service" # 新的服务名
  28. LOG_FILE="install_final.log"
  29. # ---------------------------
  30. # 日志记录函数(中文注释)
  31. # ---------------------------
  32. log_message() {
  33. local level=$1
  34. local message=$2
  35. echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message" >> "$LOG_FILE"
  36. }
  37. # ---------------------------
  38. # 输出样式函数(中文注释)
  39. # ---------------------------
  40. status_msg() { echo -e "${YELLOW}[*]${NC} $1"; }
  41. success_msg() { echo -e "${GREEN}[✓]${NC} $1"; }
  42. warning_msg() { echo -e "${YELLOW}[!]${NC} $1"; }
  43. error_msg() { echo -e "${RED}[✗]${NC} $1"; }
  44. # ---------------------------
  45. # start_step:统一步骤开始,自动增加 CURRENT_STEP,并打印美观标题
  46. # ---------------------------
  47. start_step() {
  48. # 增加当前步骤
  49. CURRENT_STEP=$((CURRENT_STEP + 1))
  50. # 打印步骤标题,保留中文说明
  51. echo
  52. echo -e "${CYAN}────────────────────────────────────────────${NC}"
  53. echo -e "${MAGENTA}▶️ 步骤 ${CURRENT_STEP}/${TOTAL_STEPS}:$1${NC}"
  54. echo -e "${CYAN}────────────────────────────────────────────${NC}"
  55. echo
  56. # 记录到日志
  57. log_message "INFO" "开始步骤 ${CURRENT_STEP}/${TOTAL_STEPS}:$1"
  58. }
  59. # ---------------------------
  60. # 修正版进度条:show_progress
  61. # 说明:
  62. # - 参数:当前值 current,总值 total,文本 text(可选)
  63. # - 避免 %0.s 的错误使用,使用 printf + tr 构造填充
  64. # - 使用 tput el 清除行尾遗留字符,防止残影
  65. # ---------------------------
  66. show_progress() {
  67. local current=$1
  68. local total=$2
  69. local text=${3:-""}
  70. # 避免除以0
  71. if [ "$total" -eq 0 ]; then
  72. total=1
  73. fi
  74. # 计算百分比(整数)
  75. local percentage=$((current * 100 / total))
  76. # 进度条长度(可调整)
  77. local bar_length=50
  78. local filled_length=$((bar_length * current / total))
  79. local empty_length=$((bar_length - filled_length))
  80. # 构造填充和空白部分(使用 printf + tr)
  81. local filled=$(printf "%${filled_length}s" | tr ' ' '#')
  82. local empty=$(printf "%${empty_length}s" | tr ' ' '-')
  83. # 旋转指示符(ASCII,避免 UTF-8 终端问题)
  84. local spinners='|/-\'
  85. # 使用 CURRENT_STEP 来驱动转轮更平滑
  86. local idx=$((CURRENT_STEP % 4))
  87. local spinner=${spinners:$idx:1}
  88. # 输出(带颜色),使用 printf 安全替换百分比
  89. printf "\r${BLUE}[${spinner}]${NC} ${GREEN}%3s%%${NC} [${GREEN}${filled}${NC}${empty}] ${text}" "$percentage"
  90. # 清除行尾残留字符
  91. # 如果 tput 不存在,也不会致命,保底
  92. if command -v tput >/dev/null 2>&1; then
  93. tput el
  94. fi
  95. }
  96. # ---------------------------
  97. # 检查 root 权限(中文注释)
  98. # ---------------------------
  99. check_root() {
  100. if [ "$(id -u)" -ne 0 ]; then
  101. error_msg "此脚本需要以root用户运行"
  102. echo -e "${YELLOW}正确命令: sudo -i${NC}"
  103. echo -e "${YELLOW}然后运行: ./install_final.sh${NC}"
  104. exit 1
  105. fi
  106. echo -e "${YELLOW}⚠️ 警告: 您正在使用root用户安装${NC}"
  107. echo
  108. }
  109. # ---------------------------
  110. # 检查主程序文件(中文注释)
  111. # ---------------------------
  112. check_program_file() {
  113. if [ ! -f "$MAIN_PROGRAM" ]; then
  114. error_msg "未找到主程序文件: $MAIN_PROGRAM"
  115. error_msg "请确保程序文件在当前目录中"
  116. log_message "ERROR" "主程序文件 $MAIN_PROGRAM 不存在"
  117. exit 1
  118. fi
  119. # 检查文件大小
  120. file_size=$(stat -c%s "$MAIN_PROGRAM")
  121. if [ $file_size -lt 1000 ]; then
  122. warning_msg "程序文件过小,可能不完整: ${file_size} bytes"
  123. log_message "WARNING" "程序文件过小: ${file_size} bytes"
  124. fi
  125. success_msg "找到主程序文件: $MAIN_PROGRAM (${file_size} bytes)"
  126. log_message "INFO" "找到主程序文件: $MAIN_PROGRAM"
  127. }
  128. # ---------------------------
  129. # 备份旧版本函数(中文注释)
  130. # ---------------------------
  131. backup_old_version() {
  132. start_step "备份旧版本"
  133. if [ -d "/opt/oled_monitor" ]; then
  134. backup_dir="/opt/oled_monitor_backup_$(date +%Y%m%d_%H%M%S)"
  135. mv /opt/oled_monitor "$backup_dir"
  136. success_msg "旧版本已备份到: $backup_dir"
  137. log_message "INFO" "旧版本备份到: $backup_dir"
  138. else
  139. status_msg "未找到旧版本,跳过备份"
  140. fi
  141. # 停止旧服务(原名)
  142. if systemctl list-units --full -all | grep -q "oled-monitor.service"; then
  143. systemctl stop oled-monitor.service > /dev/null 2>&1
  144. systemctl disable oled-monitor.service > /dev/null 2>&1
  145. success_msg "旧服务已停止并禁用"
  146. log_message "INFO" "旧服务已停止并禁用"
  147. fi
  148. # 显示进度(当前步骤 / 总步骤)
  149. show_progress $CURRENT_STEP $TOTAL_STEPS "备份完成"
  150. echo
  151. }
  152. # ---------------------------
  153. # 主安装函数(中文注释)
  154. # ---------------------------
  155. main() {
  156. # 初始化日志
  157. echo "安装日志 - $(date)" > "$LOG_FILE"
  158. log_message "INFO" "开始安装 OLED中文监控器终极修复版 v2.0"
  159. clear
  160. echo -e "${BLUE}=============================================${NC}"
  161. echo -e "${MAGENTA} OLED中文系统监控器安装脚本 v2.0${NC}"
  162. echo -e "${RED} 终极修复版 - Root用户专用${NC}"
  163. echo -e "${BLUE}=============================================${NC}"
  164. echo -e "${CYAN}彻底解决draw属性问题 | 完整依赖检查 | 详细日志${NC}"
  165. echo -e "${CYAN}全新安装目录 | 独立服务名称 | 安装后验证${NC}"
  166. echo
  167. # 检查 root
  168. check_root
  169. # 检查主程序文件
  170. check_program_file
  171. # 显示系统信息
  172. start_step "系统信息检测"
  173. status_msg "系统信息检测中..."
  174. SYSTEM_INFO=$(uname -a)
  175. echo -e "${YELLOW} 用户:${NC} $SYSTEM_USER (root)"
  176. echo -e "${YELLOW} 目录:${NC} $INSTALL_DIR"
  177. echo -e "${YELLOW} 系统:${NC} $SYSTEM_INFO"
  178. echo -e "${YELLOW} 时间:${NC} $(date)"
  179. echo -e "${YELLOW} 程序:${NC} $MAIN_PROGRAM"
  180. echo
  181. log_message "INFO" "系统信息: $SYSTEM_INFO"
  182. log_message "INFO" "安装目录: $INSTALL_DIR"
  183. show_progress $CURRENT_STEP $TOTAL_STEPS "系统信息检测完成"
  184. echo
  185. # 确认安装
  186. read -p "⚠️ 确认安装中文监控器终极修复版? (y/n): " -n 1 -r
  187. echo
  188. if [[ ! $REPLY =~ ^[Yy]$ ]]; then
  189. error_msg "安装已取消"
  190. log_message "INFO" "安装已取消"
  191. exit 0
  192. fi
  193. echo -e "\n${GREEN} 🚀 开始终极修复版安装流程...${NC}"
  194. echo
  195. #
  196. # 步骤 1: 备份旧版本
  197. #
  198. backup_old_version
  199. #
  200. # 步骤 2: 创建新的安装目录
  201. #
  202. start_step "创建全新安装目录"
  203. status_msg "正在创建目录: $INSTALL_DIR"
  204. # 确保目录不存在(若存在则清理)
  205. if [ -d "$INSTALL_DIR" ]; then
  206. rm -rf "$INSTALL_DIR"
  207. status_msg "清理旧的安装目录"
  208. log_message "INFO" "清理旧安装目录: $INSTALL_DIR"
  209. fi
  210. mkdir -p "$INSTALL_DIR"
  211. chmod 755 "$INSTALL_DIR"
  212. success_msg "全新安装目录创建完成: $INSTALL_DIR"
  213. log_message "INFO" "创建安装目录: $INSTALL_DIR"
  214. show_progress $CURRENT_STEP $TOTAL_STEPS "目录创建完成"
  215. echo
  216. #
  217. # 步骤 3: 更新系统包列表
  218. #
  219. start_step "更新系统包列表"
  220. status_msg "正在更新apt包索引..."
  221. # 使用子进程更新并显示简单进度
  222. apt-get update -y >> "$LOG_FILE" 2>&1 &
  223. pid=$!
  224. counter=0
  225. while kill -0 $pid 2>/dev/null; do
  226. counter=$((counter + 1))
  227. show_progress $CURRENT_STEP $TOTAL_STEPS "正在更新... ${counter}s"
  228. sleep 1
  229. done
  230. wait $pid 2>/dev/null
  231. if [ $? -eq 0 ]; then
  232. success_msg "包列表更新完成"
  233. log_message "INFO" "包列表更新完成"
  234. else
  235. warning_msg "包列表更新可能失败,但继续安装"
  236. log_message "WARNING" "包列表更新可能失败"
  237. fi
  238. show_progress $CURRENT_STEP $TOTAL_STEPS "包列表更新完成"
  239. echo
  240. #
  241. # 步骤 4: 安装系统依赖
  242. #
  243. start_step "安装系统依赖包"
  244. status_msg "正在安装必需的系统组件..."
  245. REQUIRED_PACKAGES="python3 python3-pip python3-pil python3-smbus i2c-tools python3-psutil python3-setuptools python3-wheel"
  246. apt-get install -y $REQUIRED_PACKAGES >> "$LOG_FILE" 2>&1 &
  247. pid=$!
  248. counter=0
  249. while kill -0 $pid 2>/dev/null; do
  250. counter=$((counter + 1))
  251. show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装依赖... ${counter}s"
  252. sleep 1
  253. done
  254. wait $pid 2>/dev/null
  255. if [ $? -eq 0 ]; then
  256. success_msg "系统依赖安装完成"
  257. log_message "INFO" "系统依赖安装完成"
  258. else
  259. warning_msg "部分依赖安装可能失败,请检查错误"
  260. log_message "WARNING" "系统依赖安装可能失败"
  261. fi
  262. show_progress $CURRENT_STEP $TOTAL_STEPS "依赖安装完成"
  263. echo
  264. #
  265. # 步骤 5: 安装中文字体
  266. #
  267. start_step "安装中文字体支持"
  268. status_msg "正在安装文泉驿中文字体..."
  269. apt-get install -y fonts-wqy-zenhei >> "$LOG_FILE" 2>&1 &
  270. pid=$!
  271. counter=0
  272. while kill -0 $pid 2>/dev/null; do
  273. counter=$((counter + 1))
  274. show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装字体... ${counter}s"
  275. sleep 1
  276. done
  277. wait $pid 2>/dev/null
  278. success_msg "中文字体安装完成"
  279. log_message "INFO" "中文字体安装完成"
  280. show_progress $CURRENT_STEP $TOTAL_STEPS "字体安装完成"
  281. echo
  282. #
  283. # 步骤 6: 验证中文字体
  284. #
  285. start_step "验证中文字体"
  286. status_msg "检查中文字体是否正确安装..."
  287. FONT_FILE="/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc"
  288. if [ -f "$FONT_FILE" ]; then
  289. success_msg "文泉驿字体安装成功: $FONT_FILE"
  290. log_message "INFO" "文泉驿字体安装成功"
  291. ls -la "$FONT_FILE" >> "$LOG_FILE" 2>&1
  292. else
  293. warning_msg "文泉驿字体未找到,尝试其他字体..."
  294. log_message "WARNING" "文泉驿字体未找到"
  295. # 检查其他中文字体
  296. OTHER_FONTS=$(find /usr/share/fonts -type f -iname "*.ttc" -o -iname "*.ttf" 2>/dev/null | grep -E "(wqy|song|hei|sim|chinese)" | head -5)
  297. if [ -n "$OTHER_FONTS" ]; then
  298. echo -e "${YELLOW}找到其他中文字体:${NC}"
  299. echo "$OTHER_FONTS"
  300. log_message "INFO" "找到其他中文字体: $OTHER_FONTS"
  301. else
  302. error_msg "未找到任何中文字体,中文显示可能受影响"
  303. log_message "ERROR" "未找到任何中文字体"
  304. fi
  305. fi
  306. show_progress $CURRENT_STEP $TOTAL_STEPS "字体验证完成"
  307. echo
  308. #
  309. # 步骤 7: 升级 pip 和 setuptools
  310. #
  311. start_step "升级Python包管理器"
  312. status_msg "正在升级pip和setuptools..."
  313. pip3 install --break-system-packages --upgrade pip setuptools wheel >> "$LOG_FILE" 2>&1 &
  314. pid=$!
  315. counter=0
  316. while kill -0 $pid 2>/dev/null; do
  317. counter=$((counter + 1))
  318. show_progress $CURRENT_STEP $TOTAL_STEPS "正在升级... ${counter}s"
  319. sleep 1
  320. done
  321. wait $pid 2>/dev/null
  322. success_msg "Python包管理器升级完成"
  323. log_message "INFO" "Python包管理器升级完成"
  324. show_progress $CURRENT_STEP $TOTAL_STEPS "包管理器升级完成"
  325. echo
  326. #
  327. # 步骤 8: 安装 Adafruit Blinka
  328. #
  329. start_step "安装Python依赖库"
  330. status_msg "正在安装Adafruit Blinka..."
  331. pip3 install --break-system-packages Adafruit-Blinka >> "$LOG_FILE" 2>&1 &
  332. pid=$!
  333. counter=0
  334. while kill -0 $pid 2>/dev/null; do
  335. counter=$((counter + 1))
  336. show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装Blinka... ${counter}s"
  337. sleep 1
  338. done
  339. wait $pid 2>/dev/null
  340. success_msg "Adafruit Blinka安装完成"
  341. log_message "INFO" "Adafruit Blinka安装完成"
  342. show_progress $CURRENT_STEP $TOTAL_STEPS "Blinka安装完成"
  343. echo
  344. #
  345. # 步骤 9: 安装 SSD1306 驱动
  346. #
  347. start_step "安装SSD1306驱动库"
  348. status_msg "正在安装OLED驱动..."
  349. pip3 install --break-system-packages adafruit-circuitpython-ssd1306 >> "$LOG_FILE" 2>&1 &
  350. pid=$!
  351. counter=0
  352. while kill -0 $pid 2>/dev/null; do
  353. counter=$((counter + 1))
  354. show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装SSD1306... ${counter}s"
  355. sleep 1
  356. done
  357. wait $pid 2>/dev/null
  358. success_msg "SSD1306驱动安装完成"
  359. log_message "INFO" "SSD1306驱动安装完成"
  360. show_progress $CURRENT_STEP $TOTAL_STEPS "驱动安装完成"
  361. echo
  362. # #
  363. # # 步骤 10: 强制重新安装 Pillow(中文显示必需)
  364. # #
  365. # start_step "强制安装Pillow库"
  366. # status_msg "正在重新安装Pillow库(中文显示必需)..."
  367. # pip3 uninstall -y pillow >> "$LOG_FILE" 2>&1 || true
  368. # pip3 install --break-system-packages --force-reinstall pillow >> "$LOG_FILE" 2>&1 &
  369. # pid=$!
  370. # counter=0
  371. # while kill -0 $pid 2>/dev/null; do
  372. # counter=$((counter + 1))
  373. # show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装Pillow... ${counter}s"
  374. # sleep 1
  375. # done
  376. # wait $pid 2>/dev/null
  377. # success_msg "Pillow库强制安装完成"
  378. # log_message "INFO" "Pillow库强制安装完成"
  379. # show_progress $CURRENT_STEP $TOTAL_STEPS "Pillow安装完成"
  380. # echo
  381. #
  382. # 步骤 10: 检查并安装 Pillow(中文显示依赖)
  383. #
  384. start_step "检查 Pillow 库(中文显示依赖)"
  385. status_msg "正在检测系统中是否已安装 Pillow 库..."
  386. # 检查 Pillow 是否存在
  387. if python3 -c "import PIL" &>/dev/null; then
  388. success_msg "系统已安装 Pillow 库,跳过安装"
  389. log_message "INFO" "Pillow 已存在,跳过安装"
  390. show_progress $CURRENT_STEP $TOTAL_STEPS "Pillow 已存在,跳过"
  391. else
  392. warn_msg "未检测到 Pillow 库,开始安装..."
  393. log_message "INFO" "开始安装 Pillow 库"
  394. (
  395. pip3 install --break-system-packages --upgrade pillow >> "$LOG_FILE" 2>&1
  396. ) &
  397. pid=$!
  398. counter=0
  399. while kill -0 $pid 2>/dev/null; do
  400. counter=$((counter + 1))
  401. show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装 Pillow... ${counter}s"
  402. sleep 1
  403. done
  404. wait $pid 2>/dev/null
  405. if python3 -c "import PIL" &>/dev/null; then
  406. success_msg "Pillow 库安装完成"
  407. log_message "INFO" "Pillow 安装成功"
  408. show_progress $CURRENT_STEP $TOTAL_STEPS "Pillow 安装完成"
  409. else
  410. error_msg "Pillow 安装失败,请检查日志"
  411. log_message "ERROR" "Pillow 安装失败"
  412. fi
  413. fi
  414. echo
  415. #
  416. # 步骤 11: 启用 I2C 接口
  417. #
  418. start_step "配置I2C接口"
  419. status_msg "正在启用并配置I2C接口..."
  420. # 尝试使用 raspi-config 非交互方式启用 I2C(若可用)
  421. if command -v raspi-config >/dev/null 2>&1; then
  422. raspi-config nonint do_i2c 0 >> "$LOG_FILE" 2>&1 || true
  423. fi
  424. # 加载 I2C 模块(兼容性处理)
  425. modprobe i2c-dev >> "$LOG_FILE" 2>&1 || true
  426. modprobe i2c-bcm2835 >> "$LOG_FILE" 2>&1 || true
  427. # 确保 /etc/modules 包含 i2c 模块(避免重复写入)
  428. if ! grep -q '^i2c-dev' /etc/modules 2>/dev/null; then
  429. echo "i2c-dev" >> /etc/modules
  430. fi
  431. if ! grep -q '^i2c-bcm2835' /etc/modules 2>/dev/null; then
  432. echo "i2c-bcm2835" >> /etc/modules
  433. fi
  434. # 更新 config.txt(只追加一次)
  435. if ! grep -q '^dtparam=i2c_arm=on' /boot/config.txt 2>/dev/null; then
  436. echo "dtparam=i2c_arm=on,i2c_arm_baudrate=400000" >> /boot/config.txt
  437. fi
  438. sleep 2
  439. success_msg "I2C接口配置完成"
  440. log_message "INFO" "I2C接口配置完成"
  441. show_progress $CURRENT_STEP $TOTAL_STEPS "I2C配置完成"
  442. echo
  443. #
  444. # 步骤 12: 检测 I2C 设备
  445. #
  446. start_step "检测I2C设备"
  447. status_msg "正在扫描I2C总线..."
  448. echo -e "${YELLOW}I2C设备列表:${NC}"
  449. i2cdetect -y 1 | tee -a "$LOG_FILE" 2>&1
  450. # 检查 OLED 设备地址(3c 或 3d)
  451. OLED_FOUND=$(i2cdetect -y 1 | grep -E "(3c|3d)" || true)
  452. if [ -n "$OLED_FOUND" ]; then
  453. success_msg "✅ 检测到OLED设备: $OLED_FOUND"
  454. log_message "INFO" "检测到OLED设备: $OLED_FOUND"
  455. else
  456. error_msg "❌ 未检测到OLED设备"
  457. error_msg "请检查OLED屏幕接线和电源"
  458. log_message "ERROR" "未检测到OLED设备"
  459. # 显示接线提示(中文)
  460. echo -e "${CYAN}接线提示:${NC}"
  461. echo -e " VCC -> 3.3V (Pin 1)"
  462. echo -e " GND -> GND (Pin 6)"
  463. echo -e " SDA -> SDA (Pin 3)"
  464. echo -e " SCL -> SCL (Pin 5)"
  465. echo
  466. read -p "⚠️ 确认继续安装? (y/n): " -n 1 -r
  467. echo
  468. if [[ ! $REPLY =~ ^[Yy]$ ]]; then
  469. error_msg "安装已取消"
  470. log_message "INFO" "用户取消安装"
  471. exit 0
  472. fi
  473. fi
  474. show_progress $CURRENT_STEP $TOTAL_STEPS "I2C检测完成"
  475. echo
  476. #
  477. # 步骤 13: 复制程序文件到安装目录
  478. #
  479. start_step "部署程序文件"
  480. status_msg "正在复制终极修复版程序..."
  481. cp "$MAIN_PROGRAM" "$INSTALL_DIR/" 2>>"$LOG_FILE" || abort "复制主程序失败,请检查权限"
  482. chmod 755 "$INSTALL_DIR/$MAIN_PROGRAM"
  483. # 创建配置 & 日志目录
  484. mkdir -p "$INSTALL_DIR/config"
  485. chmod 755 "$INSTALL_DIR/config"
  486. mkdir -p "$INSTALL_DIR/logs"
  487. chmod 755 "$INSTALL_DIR/logs"
  488. success_msg "程序文件部署完成"
  489. log_message "INFO" "程序文件部署完成"
  490. echo -e "${YELLOW}文件列表:${NC}"
  491. ls -la "$INSTALL_DIR/" | tee -a "$LOG_FILE"
  492. show_progress $CURRENT_STEP $TOTAL_STEPS "文件部署完成"
  493. echo
  494. #
  495. # 步骤 14: 设置权限
  496. #
  497. start_step "设置系统权限"
  498. status_msg "正在配置文件权限..."
  499. chown -R "$SYSTEM_USER:$SYSTEM_GROUP" "$INSTALL_DIR"
  500. chmod -R 755 "$INSTALL_DIR"
  501. # 设置日志文件权限
  502. touch "$INSTALL_DIR/logs/monitor.log"
  503. chmod 644 "$INSTALL_DIR/logs/monitor.log"
  504. chown "$SYSTEM_USER:$SYSTEM_GROUP" "$INSTALL_DIR/logs/monitor.log"
  505. # 验证权限并列出
  506. echo -e "${YELLOW}权限验证:${NC}"
  507. ls -ld "$INSTALL_DIR"
  508. ls -la "$INSTALL_DIR/$MAIN_PROGRAM"
  509. success_msg "权限设置完成"
  510. log_message "INFO" "权限设置完成"
  511. show_progress $CURRENT_STEP $TOTAL_STEPS "权限配置完成"
  512. echo
  513. #
  514. # 步骤 15: 创建 systemd 服务(终极修复版)
  515. #
  516. start_step "创建系统服务"
  517. status_msg "正在配置systemd服务..."
  518. cat > "/etc/systemd/system/$SERVICE_NAME" << EOF
  519. [Unit]
  520. Description=OLED中文系统监控器(终极修复版)
  521. After=network.target i2c-dev.service systemd-modules-load.service
  522. Wants=i2c-dev.service
  523. [Service]
  524. Type=simple
  525. User=$SYSTEM_USER
  526. Group=$SYSTEM_GROUP
  527. WorkingDirectory=$INSTALL_DIR
  528. ExecStart=/usr/bin/python3 $INSTALL_DIR/$MAIN_PROGRAM >> $INSTALL_DIR/logs/monitor.log 2>&1
  529. Restart=always
  530. RestartSec=10
  531. Environment="PYTHONPATH=/usr/local/lib/python3.9/dist-packages:/usr/lib/python3/dist-packages"
  532. Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
  533. # 终极修复版特殊配置
  534. ExecStartPre=/bin/sleep 5
  535. ExecStartPre=/bin/chmod 755 $INSTALL_DIR/$MAIN_PROGRAM
  536. ExecStartPre=/bin/bash -c "modprobe i2c-dev; modprobe i2c-bcm2835"
  537. [Install]
  538. WantedBy=multi-user.target
  539. EOF
  540. # 重新加载 systemd 单元
  541. systemctl daemon-reload
  542. success_msg "系统服务创建完成"
  543. log_message "INFO" "系统服务创建完成"
  544. show_progress $CURRENT_STEP $TOTAL_STEPS "服务创建完成"
  545. echo
  546. #
  547. # 步骤 16: 启动服务并测试
  548. #
  549. start_step "启动并测试服务"
  550. status_msg "正在启动终极修复版监控器服务..."
  551. # 尝试停止同名服务(以防重复)
  552. systemctl stop "$SERVICE_NAME" > /dev/null 2>&1 || true
  553. # 启用并启动服务
  554. systemctl enable "$SERVICE_NAME" >> "$LOG_FILE" 2>&1
  555. systemctl start "$SERVICE_NAME" >> "$LOG_FILE" 2>&1 || true
  556. # 等待一段时间观察服务是否启动
  557. echo -e "${YELLOW}等待服务启动...${NC}"
  558. for i in {1..10}; do
  559. show_progress $CURRENT_STEP $TOTAL_STEPS "服务启动中... ${i}s"
  560. sleep 1
  561. done
  562. echo
  563. # 检查服务状态
  564. if systemctl is-active --quiet "$SERVICE_NAME"; then
  565. success_msg "🎉 终极修复版服务启动成功!"
  566. log_message "INFO" "服务启动成功"
  567. # 显示服务信息(短)
  568. echo -e "${CYAN}服务信息:${NC}"
  569. systemctl status "$SERVICE_NAME" --no-pager -l | sed -n '1,10p'
  570. echo
  571. # 显示实时日志(前10行)
  572. echo -e "\n${CYAN}实时日志(前10行):${NC}"
  573. tail -n 10 "$INSTALL_DIR/logs/monitor.log"
  574. else
  575. error_msg "服务启动失败"
  576. log_message "ERROR" "服务启动失败"
  577. echo -e "${YELLOW}错误日志(journalctl 末尾):${NC}"
  578. journalctl -u "$SERVICE_NAME" --no-pager -n 20
  579. echo -e "${YELLOW}监控器日志:${NC}"
  580. if [ -f "$INSTALL_DIR/logs/monitor.log" ]; then
  581. tail -n 20 "$INSTALL_DIR/logs/monitor.log"
  582. fi
  583. warning_msg "请检查错误日志并重新安装"
  584. fi
  585. show_progress $CURRENT_STEP $TOTAL_STEPS "服务启动完成"
  586. echo
  587. #
  588. # 安装后验证(附加检查)
  589. #
  590. start_step "安装后验证"
  591. status_msg "正在验证安装结果..."
  592. PROCESS_COUNT=$(ps aux | grep "$MAIN_PROGRAM" | grep -v grep | wc -l)
  593. if [ "$PROCESS_COUNT" -gt 0 ]; then
  594. success_msg "✅ 程序正在运行,进程数: $PROCESS_COUNT"
  595. log_message "INFO" "程序正在运行,进程数: $PROCESS_COUNT"
  596. echo -e "${YELLOW}运行中的进程:${NC}"
  597. ps aux | grep "$MAIN_PROGRAM" | grep -v grep
  598. else
  599. warning_msg "⚠️ 未检测到运行中的程序进程"
  600. log_message "WARNING" "未检测到运行中的程序进程"
  601. fi
  602. # 检查文件完整性
  603. if [ -f "$INSTALL_DIR/$MAIN_PROGRAM" ]; then
  604. file_size=$(stat -c%s "$INSTALL_DIR/$MAIN_PROGRAM")
  605. success_msg "✅ 程序文件完整: ${file_size} bytes"
  606. log_message "INFO" "程序文件完整: ${file_size} bytes"
  607. else
  608. error_msg "❌ 程序文件缺失"
  609. log_message "ERROR" "程序文件缺失"
  610. fi
  611. show_progress $CURRENT_STEP $TOTAL_STEPS "安装验证完成"
  612. echo
  613. # 最终完成提示
  614. echo -e "\n\n${GREEN}=============================================${NC}"
  615. echo -e "${MAGENTA}🎉 OLED中文监控器终极修复版安装完成!${NC}"
  616. echo -e "${GREEN}=============================================${NC}"
  617. echo
  618. echo -e "${YELLOW}📊 安装统计:${NC}"
  619. echo -e " 总步骤: $TOTAL_STEPS"
  620. echo -e " 完成率: 100%"
  621. echo -e " 安装目录: $INSTALL_DIR"
  622. echo -e " 主程序: $MAIN_PROGRAM"
  623. echo -e " 服务名称: $SERVICE_NAME"
  624. echo -e " 日志文件: $LOG_FILE"
  625. echo
  626. echo -e "${CYAN}🔧 管理命令:${NC}"
  627. echo -e " 📖 查看日志: journalctl -u $SERVICE_NAME -f"
  628. echo -e " 📖 程序日志: tail -f $INSTALL_DIR/logs/monitor.log"
  629. echo -e " 🛑 停止服务: systemctl stop $SERVICE_NAME"
  630. echo -e " 🔁 重启服务: systemctl restart $SERVICE_NAME"
  631. echo -e " 📊 查看状态: systemctl status $SERVICE_NAME"
  632. echo -e " 📁 程序目录: cd $INSTALL_DIR && ls -la"
  633. echo -e " 🧪 测试运行: cd $INSTALL_DIR && python3 $MAIN_PROGRAM"
  634. echo
  635. echo -e "${YELLOW}💡 终极修复特色:${NC}"
  636. echo -e " - 彻底解决draw属性初始化问题"
  637. echo -e " - 多层备用机制确保稳定运行"
  638. echo -e " - 详细的调试日志和错误处理"
  639. echo -e " - 智能I2C地址检测"
  640. echo -e " - 自动字体安装和验证"
  641. echo -e " - 全新的安装目录避免冲突"
  642. echo
  643. echo -e "${RED}⚠️ 重要提醒:${NC}"
  644. echo -e " - 如果服务启动失败,请查看详细日志"
  645. echo -e " - 安装日志已保存到: $LOG_FILE"
  646. echo -e " - 程序日志已保存到: $INSTALL_DIR/logs/monitor.log"
  647. echo -e " - OLED屏幕应显示中文监控信息"
  648. echo -e " - 如有问题请提供完整日志文件"
  649. echo
  650. echo -e "${GREEN}=============================================${NC}"
  651. echo -e "${MAGENTA}终极修复版安装完成!祝您使用愉快!${NC}"
  652. echo -e "${GREEN}=============================================${NC}"
  653. log_message "INFO" "终极修复版安装完成"
  654. }
  655. # ---------------------------
  656. # 帮助函数:在必要处退出并记录日志
  657. # ---------------------------
  658. abort() {
  659. echo -e "${RED}安装中遇到致命错误:$1${NC}"
  660. log_message "ERROR" "$1"
  661. exit 1
  662. }
  663. # 启动主函数
  664. main