news 2026/9/3 4:53:54

N1搭建守护环境以及重装 Armbian 后完整恢复整套守护环境,清理日志步骤

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
N1搭建守护环境以及重装 Armbian 后完整恢复整套守护环境,清理日志步骤

一,从零搭建守护环境

1,在 root 目录下新建 all-n1-install.sh 文件,内容如下

#!/bin/bashset-eecho"==== N1盒子自愈全套【无jq版·重新生成守护环境】 ===="# 不再安装jq依赖echo"[1/7] 跳过jq依赖,使用pm2 id返回码判断状态"# 2.生成 /root/n1.shecho"[2/7] 生成 /root/n1.sh"cat>/root/n1.sh<<'INNER_EOF' #!/bin/bash # N1盒子服务自愈脚本【无jq最终版】 # 宿主机服务: go-cqhttp sillyGirl xdd # 青龙容器内服务:默认关闭巡检 QL_APPS=() QL_CONTAINER="qinglong" LOCK_DIR="/root/.n1-deploy" LOG_FILE="/root/ql/logs/selfheal.log" CRON_LOG="/root/ql/logs/cron-n1.log" PM2_LOG_DIR="/root/.pm2/logs" mkdir -p "${LOCK_DIR}" mkdir -p "/root/ql/logs" mkdir -p "${PM2_LOG_DIR}" # ====================== 配置参数 ====================== log_max_size=$((20*1024*1024)) # 单文件上限 20MB log_keep_days=3 # 碎片日志保留天数 docker_exec_timeout=8 # docker exec超时秒数 # ===================================================== ## ① 主日志超过阈值清空 for logfile in "${LOG_FILE}" "${CRON_LOG}";do if [ -f "${logfile}" ];then filesize=$(stat -c%s "${logfile}") if [ "${filesize}" -gt "${log_max_size}" ];then > "${logfile}" fi fi done ## ② 碎片日志过期删除 find /root/ql/logs -type f -name "*.log" ! -name "selfheal.log" ! -name "cron-n1.log" -mtime +${log_keep_days} -delete ## ③ 宿主机pm2日志处理 for logfile in ${PM2_LOG_DIR}/*.log;do if [ -f "${logfile}" ];then filesize=$(stat -c%s "${logfile}") if [ "${filesize}" -gt "${log_max_size}" ];then > "${logfile}" fi fi done find "${PM2_LOG_DIR}" -type f -name "*.log" -mtime +${log_keep_days} -delete ## ④ docker容器日志截断 docker_log_path=$(docker inspect --format='{{.LogPath}}' "${QL_CONTAINER}" 2>/dev/null || true) if [ -n "${docker_log_path}" ] && [ -f "${docker_log_path}" ];then docker_log_size=$(stat -c%s "${docker_log_path}") if [ "${docker_log_size}" -gt "${log_max_size}" ];then truncate -s 0 "${docker_log_path}" fi fi # 互斥锁,防止脚本并发运行 exec 9>"${LOCK_DIR}/n1.lock" if ! flock -n 9 ; then echo "$(date '+%Y-%m-%d %H:%M:%S') n1.sh 已在运行,放弃本次执行" >> ${LOG_FILE} exit 0 fi log(){ echo "$(date '+%Y-%m-%d %H:%M:%S') $*" >> ${LOG_FILE} echo "$*" } # ---------------- pm2 id方式检测,无jq ---------------- host_is_online(){ local app="$1" pm2 id "${app}" >/dev/null 2>&1 return $? } ql_is_online(){ local app="$1" docker exec --timeout ${docker_exec_timeout} "${QL_CONTAINER}" pm2 id "${app}" >/dev/null 2>&1 return $? } HOST_APPS=("go-cqhttp" "sillyGirl" "xdd") QL_APPS=() log "=== N1 夜维 $(date '+%Y-%m-%d_%H:%M') ===" # 宿主机服务巡检 host_ok=0 host_total=${#HOST_APPS[@]} for app in "${HOST_APPS[@]}";do if host_is_online "${app}";then log "✅ 腿[${app}] online" host_ok=$((host_ok+1)) else log "⚠️ 腿[${app}] 异常,执行重启" log "🔧 重启宿主机 ${app}" pm2 restart "${app}" >>${LOG_FILE} 2>&1 fi done log "${host_ok}/${host_total}" # 容器服务巡检,QL_APPS为空数组时不会循环执行 ql_ok=0 ql_total=${#QL_APPS[@]} for app in "${QL_APPS[@]}";do if ql_is_online "${app}";then log "✅ ql[${app}] online" ql_ok=$((ql_ok+1)) else log "⚠️ ql[${app}] 异常,执行重启" log "🔧 重启容器 ${app}" docker exec --timeout ${docker_exec_timeout} "${QL_CONTAINER}" pm2 restart "${app}" >>${LOG_FILE} 2>&1 fi done log "${ql_ok}/${ql_total}" disk_used=$(df -P / | awk 'NR==2{print $5}' | tr -d '%') log "✅ 磁盘 ${disk_used}%" log "=== 巡检结束 ===" exit 0 INNER_EOFchmod+x /root/n1.sh# 3.生成systemd开机恢复服务:宿主机pm2 resurrect + 容器pm2 resurrectecho"[3/7] 生成 systemd 开机延时恢复服务"cat>/etc/systemd/system/n1-ql-restore.service<<'UNIT_EOF' [Unit] Description=N1开机延时恢复宿主机&青龙容器pm2 After=docker.service Requires=docker.service [Service] Type=oneshot ExecStart=/bin/sh -c 'sleep 40; pm2 resurrect >/dev/null 2>&1; pm2 save >/dev/null 2>&1; docker exec qinglong pm2 resurrect >/dev/null 2>&1; docker exec qinglong pm2 save >/dev/null 2>&1;' [Install] WantedBy=multi-user.target UNIT_EOFsystemctl daemon-reload systemctlenablen1-ql-restore.service# 4.配置crontab:覆盖式写入干净定时,避免重复任务echo"[4/7] 设置crontab定时任务,覆盖旧定时"cat>/root/tmp_cron.txt<<'CRON_EOF' 05 3 * * * /root/ql-scrub.sh >> /root/ql/logs/night.log 2>&1 15 3 * * * /root/n1.sh */5 * * * * /bin/bash /root/n1.sh CRON_EOFcrontab/root/tmp_cron.txtrm-f/root/tmp_cron.txt# 5.生成日志清理脚本 ql‑scrub.shecho"[5/7] 生成日志裁剪脚本 ql‑scrub.sh"cat>/root/ql-scrub.sh<<'SCRUB_EOF' #!/bin/bash LOGDIR="/root/ql/logs" MAX_SIZE=$((1024*1024*20)) #20MB mkdir -p "${LOGDIR}" for logfile in "${LOGDIR}"/*.log;do if [ -f "${logfile}" ];then filesize=$(stat -c%s "${logfile}") if [ "${filesize}" -gt "${MAX_SIZE}" ];then mv -f "${logfile}" "${logfile}.old" touch "${logfile}" fi fi done SCRUB_EOFchmod+x /root/ql-scrub.sh# 6.清理旧锁、创建目录echo"[6/7] 清理旧锁文件,创建目录"rm-f/root/.n1-deploy/n1.lockmkdir-p/root/ql/logsmkdir-p/root/.pm2/logs# 7.首次执行测试echo"[7/7] 执行首次巡检测试"bash/root/n1.shecho""echo"==================== 部署完成 ===================="echo"✅ 完全无jq依赖,pm2 id返回码检测进程"echo"✅ QL_APPS=() 默认关闭容器内pm2巡检,无需手动修改"echo"✅ systemd:开机40秒后恢复宿主机+青龙容器pm2"echo"✅ crontab:5分钟巡检;凌晨3:05日志清理;3:15额外巡检"echo"✅ 日志策略:单文件>20MB轮转;碎片日志保留3天"echo"✅ 巡检对象:宿主机go‑cqhttp/sillyGirl/xdd"echo"✅ flock防并发、docker exec超时8秒保护"echo""echo"手动巡检命令:bash /root/n1.sh"echo"查看自愈日志:tail -f /root/ql/logs/selfheal.log"echo"查看开机恢复服务状态:systemctl status n1-ql-restore.service"echo"查看定时任务:crontab -l"echo""echo"👉 青龙容器内部建议执行:pm2 resurrect && pm2 save"echo"👉 整机重启测试:reboot"

2,脚本跑完校验

crontab-lsystemctl status n1-ql-restore.servicebash/root/n1.sh

只会输出宿主机三条 ✅ xxx online,容器部分不会输出任何内容

使用场景:N1 彻底重装 Armbian 从零部署守护环境就运行这个脚本

二,备份守护环境

1,确认全部 5 个文件都存在

ls-l\/root/n1.sh\/root/ql-scrub.sh\/etc/systemd/system/n1-ql-restore.service\/root/cron_backup.txt\/root/pm2_ecosystem_backup.json

上面命令不报错,列出全部文件,就可以打包

crontab-l>/root/cron_backup.txt pm2 ecosystem>/root/pm2_ecosystem_backup.jsontar-zcvf/root/n1_backup.tar.gz\/root/n1.sh\/root/ql-scrub.sh\/etc/systemd/system/n1-ql-restore.service\/root/cron_backup.txt\/root/pm2_ecosystem_backup.json

2,查看包里文件清单确认

tar-ztvf/root/n1_backup.tar.gz

3,能看到 5 个文件就全部正常

root/n1.sh root/ql-scrub.sh etc/systemd/system/n1-ql-restore.service root/cron_backup.txt root/pm2_ecosystem_backup.json

4,看备份包大小

ls-lh/root/n1_backup.tar.gz

📌现在这个备份包,是基于无‑jq 一键脚本生成出来的环境打包出来的

  • n1.sh:QL_APPS=()默认关闭容器巡检、pm2 id 判断、无 jq
  • ql‑scrub.sh:日志轮转脚本
  • systemd 服务:开机 40s 同时恢复宿主机 pm2 + 青龙容器 pm2
  • cron_backup.txt:保存当前干净的 3 条定时
  • pm2_ecosystem_backup.json:pm2 进程清单备份

三,N1 重装 Armbian 之后完整恢复整套守护环境

这个备份只保存自愈守护相关:巡检脚本、日志清理、systemd 开机服务、定时任务、pm2 进程清单

✅ n1.sh 自愈脚本:使用pm2 id判断进程,彻底避开 pm2 jq 解析 bug,go‑cqhttp/sillyGirl/xdd 识别 online,不会误重启
✅ ql‑scrub.sh 日志裁剪脚本重建完成,防止日志打爆磁盘
✅ systemd n1‑ql‑restore.service:开机延时恢复 pm2
✅ crontab 定时已精简,无重复任务,无宝塔旧垃圾定时
✅ flock 锁防止脚本并发重复运行
✅ 备份包包含全部守护逻辑脚本、systemd 服务、定时导出、pm2 进程清单

1,N1 重装 Armbian ,点我

2,安装好宝塔、docker、pm2、青龙容器、go‑cqhttp、sillyGirl、xdd

3,把备份的n1_backup.tar.gz上传到宝塔 root 目录下,然后依次执行

tar-zxvf/root/n1_backup.tar.gz-C/chmod+x /root/n1.shchmod+x /root/ql-scrub.shcrontab/root/cron_backup.txt systemctl daemon-reload systemctlenablen1-ql-restore.service pm2 start /root/pm2_ecosystem_backup.json pm2 savemkdir-p/root/ql/logsbash/root/n1.sh

执行完最后一条 bash /root/n1.sh,输出三条 ✅ xxx online,代表整套自愈恢复成功

4,恢复完成后校验

#1. 确认定时任务加载正确crontab-l#2. 确认开机自启服务已经启用systemctl status n1-ql-restore.service#3. 再手动跑一次自愈脚本确认状态bash/root/n1.sh

✅预期输出

===N1 夜维 xxxx===✅ 腿[go-cqhttp]online ✅ 腿[sillyGirl]online ✅ 腿[xdd]online3/30/0 ✅ 磁盘 xx%===巡检结束===
#4. 看实时日志是否正常写入tail-n20/root/ql/logs/selfheal.log

5,可选,整机重启测试(最重要的验证)

reboot

盒子重启,SSH 重新登录进来

#重启登录后检查pm2 listbash/root/n1.sh

重启后 pm2 三个进程能自动拉起来、自愈脚本识别全部 online,代表完整恢复成功

后台自动工作:

①每 5 分钟自动运行 /root/n1.sh,进程挂掉自动重启
②凌晨 3:05 运行日志清理脚本,防止日志占磁盘
③开机 systemd 服务自动恢复 pm2 进程

6,日常排查命令

crontab-l# 核对定时任务systemctl status n1-ql-restore.service# 核对开机恢复服务已启用bash/root/n1.sh# 手动跑一遍自愈脚本,确认全部onlinetail-n20/root/ql/logs/selfheal.log# 查看最近20行日志,确认日志写入正常
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/3 4:52:55

STM32F0标准外设库V1.5.0:搭建最小工程与避坑指南

简介&#xff1a;嵌入式开发中&#xff0c;固件库的选择直接影响项目进度与维护成本。STM32F0作为入门级Cortex-M0芯片&#xff0c;广泛用于成本敏感的控制器设计&#xff0c;其标准外设库&#xff08;StdPeriph&#xff09;通过封装寄存器操作&#xff0c;提供GPIO、USART等通…

作者头像 李华
网站建设 2026/9/3 4:52:05

基于STM32F103C8T6的三相SPWM逆变电源:从硬件设计到软件实现全解析

简介&#xff1a;本资源是一套基于STM32F103C8T6单片机实现的三相SPWM逆变电源完整开发套件&#xff0c;面向嵌入式电力电子方向的本科生、研究生及硬件工程师&#xff0c;解决三相正弦波脉宽调制驱动、IGBT功率级控制与PCB工程落地等核心实践难题。压缩包共385个文件&#xff…

作者头像 李华
网站建设 2026/9/3 4:51:34

AI电影级Skill:从文本蓝图到视频创作的结构化流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/3 4:51:03

基于vnpy的量化交易AI工程化实践闭环

简介&#xff1a;本资源是一个面向量化交易开发者与金融AI学习者的实战型测试项目&#xff0c;基于开源vnpy框架集成机器学习与深度学习算法&#xff0c;覆盖金融时间序列预测、市场情绪分析、高频信号挖掘、多因子建模、投资组合优化及回测验证等核心环节&#xff0c;解决策略…

作者头像 李华
网站建设 2026/9/3 4:47:01

基于Qt5与PLC通信库的工业数据采集与监控系统开发实战

简介&#xff1a;这是一套面向工业自动化初学者与Qt开发者的个人学习实践项目&#xff0c;聚焦于Windows平台下PLC数据交互工具的完整实现&#xff0c;解决工业现场设备通信与可视化监控的技术落地问题。资源包共21个文件&#xff0c;含3个核心头文件&#xff08;.h&#xff09…

作者头像 李华
网站建设 2026/9/3 4:46:49

Aspen Plus在二甲醚羰基化合成乙酸甲酯工艺开发中的应用实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华