autorun.sh 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. #!/bin/bash
  2. # 定义颜色
  3. RED='\033[31m'
  4. GREEN='\033[32m'
  5. YELLOW='\033[33m'
  6. BLUE='\033[34m'
  7. PH='\033[35m'
  8. QS='\033[36m'
  9. NC='\033[0m' # No Color
  10. echo -e "${PH}警告:此脚本只适用于Debian系列系统(包含Ubuntu),因为需要使用apt来安装软件。${NC}"
  11. echo -e "${PH}警告:此脚本只适用于Debian系列系统(包含Ubuntu),因为需要使用apt来安装软件。${NC}"
  12. echo -e "${PH}警告:此脚本只适用于Debian系列系统(包含Ubuntu),因为需要使用apt来安装软件。${NC}"
  13. echo -e "${YELLOW}警告:如果是群晖NAS自行安装node套件后同样可以使用脚本进行更新使用!!!${NC}"
  14. echo -e "${GREEN}警告:脚本自动更新需要自行添加任务计划设定运行时间!!!${NC}"
  15. # 检查是否为群晖系统
  16. is_syno_system() {
  17. # 群晖系统通常会有 /etc.defaults/VERSION 文件
  18. if [ -f /etc.defaults/VERSION ]; then
  19. return 0
  20. else
  21. return 1
  22. fi
  23. }
  24. # 检查是否为群晖系统
  25. if is_syno_system; then
  26. echo -e "${QS}检测到群晖系统,跳过apt检查。${NC}"
  27. else
  28. # 检查系统是否支持apt
  29. if ! command -v apt >/dev/null 2>&1; then
  30. echo -e "${GREEN}错误:不支持的系统。${NC}"
  31. exit 1
  32. fi
  33. fi
  34. # 检查Node.js版本
  35. check_node_version() {
  36. local node_version=$(node -v)
  37. if [[ "$node_version" < "v20.0.0" ]]; then
  38. echo -e "${YELLOW}Node.js版本低于20.0.0,正在安装Node.js v20以上版本...${NC}"
  39. install_node_v20
  40. npm config set registry https://registry.npmmirror.com
  41. else
  42. echo -e "${GREEN}Node.js版本符合要求(v20以上),跳过安装。${NC}"
  43. fi
  44. }
  45. # 安装Node.js v20以上版本
  46. install_node_v20() {
  47. echo -e "${YELLOW}正在安装NVM...${NC}"
  48. curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
  49. # 启用NVM
  50. export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
  51. [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
  52. # 安装Node.js 20.18.1
  53. echo -e "${YELLOW}正在安装Node.js 20.18.1...${NC}"
  54. nvm install 20.18.1
  55. # 设置默认Node.js版本
  56. nvm alias default 20.18.1
  57. echo -e "${GREEN}Node.js 20.18.1安装完成。${NC}"
  58. }
  59. # 检查NVM是否存在,如果不存在则安装
  60. if command -v nvm >/dev/null 2>&1; then
  61. echo -e "${GREEN}NVM已安装,跳过NVM安装。${NC}"
  62. else
  63. echo -e "${YELLOW}NVM未安装,正在安装NVM...${NC}"
  64. curl -o- https://gitee.com/RubyMetric/nvm-cn/raw/main/install.sh | bash
  65. export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
  66. [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
  67. [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
  68. echo -e "${GREEN}NVM安装完成。${NC}"
  69. fi
  70. # 安装Yarn和PM2
  71. install_yarn_and_pm2() {
  72. if command -v yarn >/dev/null 2>&1; then
  73. echo -e "${GREEN}Yarn已安装,跳过Yarn安装。${NC}"
  74. yarn config set registry https://registry.yarnpkg.com
  75. else
  76. echo -e "${YELLOW}Yarn未安装,正在安装Yarn...${NC}"
  77. nvm install-node # 安装最新版本的Node.js,自动选择大于v20的版本
  78. nvm use default
  79. npm install -g yarn
  80. yarn config set registry https://registry.yarnpkg.com
  81. if [ $? -ne 0 ]; then
  82. echo -e "${RED}Yarn安装失败,请手动安装Yarn后重试。${NC}"
  83. exit 1
  84. fi
  85. echo -e "${GREEN}Yarn安装成功。${NC}"
  86. fi
  87. if command -v pm2 >/dev/null 2>&1; then
  88. echo -e "${GREEN}PM2已安装,跳过PM2安装。${NC}"
  89. else
  90. echo -e "${YELLOW}PM2未安装,正在安装PM2...${NC}"
  91. npm install -g pm2
  92. if [ $? -ne 0 ]; then
  93. echo -e "${RED}PM2安装失败,请手动安装PM2后重试。${NC}"
  94. exit 1
  95. fi
  96. echo -e "${GREEN}PM2安装成功。${NC}"
  97. fi
  98. }
  99. # 执行Node.js版本检查
  100. check_node_version
  101. # 安装Yarn和PM2
  102. install_yarn_and_pm2
  103. # 提示用户输入需要创建的目录,30秒后自动使用当前目录
  104. echo -ne "${PH}请输入需要创建的目录路径(30秒内无输入则使用当前目录):${NC}"
  105. read -t 30 dir_path
  106. echo
  107. # 根据用户输入设置目录
  108. if [[ -n $dir_path ]]; then
  109. mkdir -p "$dir_path" && cd "$dir_path"
  110. if [ $? -eq 0 ]; then
  111. echo -e "${GREEN}目录 '$dir_path' 创建并进入成功。${NC}"
  112. REPO_DIR="$dir_path"
  113. else
  114. echo -e "${RED}目录 '$dir_path' 创建失败,使用当前目录。${NC}"
  115. REPO_DIR=$(pwd)
  116. fi
  117. else
  118. echo -e "${YELLOW}已超时,使用当前目录:$(pwd)"
  119. REPO_DIR=$(pwd)
  120. fi
  121. # 远程仓库地址
  122. REMOTE_REPO="https://github.com/hjdhnx/drpy-node.git"
  123. # 代理远程仓库地址
  124. echo -e "${YELLOW}如果拉取不顺利,请在脚本中找到$REMOTE_REPO自行注释修改为kk代理地址${NC}"
  125. #REMOTE_REPO="https://kkgithub.com/hjdhnx/drpy-node.git"
  126. # 项目名称
  127. PROJECT_NAME="drpy-node"
  128. # 获取设备IP地址
  129. get_device_ip() {
  130. # 使用curl获取公网IP地址
  131. # 这里使用的是ipinfo.io服务,你也可以使用其他服务
  132. IP=$(curl -s https://ipinfo.io/ip)
  133. if [ $? -eq 0 ]; then
  134. echo -e "${QS}= 设备IP地址:$IP${NC}"
  135. echo -e "${QS}= 公网IP自行打码${NC}"
  136. return 0
  137. else
  138. echo -e "${RED}无法获取设备IP地址。${NC}"
  139. return 1
  140. fi
  141. }
  142. # 获取设备局域网IP地址
  143. get_local_ip() {
  144. # 使用ip命令获取局域网IP地址
  145. local ip=$(ip addr show scope global | grep inet | grep -v inet6 | grep -v '127.0.0.1' | awk '{print $2}' | cut -d/ -f1 | head -n1)
  146. if [ -n "$ip" ]; then
  147. echo -e "$ip"
  148. else
  149. echo -e "${RED}无法获取局域网IP地址。${NC}"
  150. exit 1
  151. fi
  152. }
  153. # 获取局域网IP地址
  154. LOCAL_IP=$(get_local_ip)
  155. # 定义创建env.json文件的函数
  156. create_env_json() {
  157. local env_json_path="$1/config/env.json"
  158. # 检查env.json文件是否存在
  159. if [ ! -f "$env_json_path" ]; then
  160. echo -e "${YELLOW}env.json文件不存在,正在创建...${NC}"
  161. # 创建env.json文件并填充默认内容
  162. cat > "$env_json_path" <<EOF
  163. {
  164. "ali_token": "",
  165. "ali_refresh_token": "",
  166. "quark_cookie": "",
  167. "uc_cookie": "",
  168. "bili_cookie": "",
  169. "thread": "10"
  170. }
  171. EOF
  172. if [ $? -eq 0 ]; then
  173. echo -e "${GREEN}env.json文件创建成功。${NC}"
  174. else
  175. echo -e "${RED}env.json文件创建失败。${NC}"
  176. exit 1
  177. fi
  178. else
  179. echo -e "${YELLOW}env.json文件已存在,无需创建。${NC}"
  180. fi
  181. }
  182. # 定义创建.env文件的函数
  183. create_default_env() {
  184. local env_path="$1/.env"
  185. local env_development_path="$1/.env.development"
  186. # 检查.env文件是否存在
  187. if [ ! -f "$env_path" ]; then
  188. echo -e "${YELLOW}.env文件不存在,正在使用.env.development作为模板创建...${NC}"
  189. # 使用.env.development作为模板创建.env文件
  190. cp "$env_development_path" "$env_path"
  191. if [ $? -eq 0 ]; then
  192. echo -e "${GREEN}.env文件创建成功。${NC}"
  193. else
  194. echo -e "${RED}.env文件创建失败。${NC}"
  195. exit 1
  196. fi
  197. else
  198. echo -e "${YELLOW}.env文件已存在,无需创建。${NC}"
  199. fi
  200. }
  201. # 定义初始化.env文件的函数
  202. initialize_default_env() {
  203. local env_path="$1/.env"
  204. local env_development_path="$1/.env.development"
  205. # 检查.env文件是否存在
  206. if [ ! -f "$env_path" ]; then
  207. echo -e "${YELLOW}.env文件不存在,正在使用.env.development作为模板创建...${NC}"
  208. # 提示用户输入自定义值,并设置30秒超时
  209. echo -ne "${YELLOW}请输入网盘入库密码(30秒内无输入则使用默认值'drpys'直接回车可跳过):${NC}"
  210. read -t 30 dir_path
  211. echo
  212. if [ -z "$cookie_auth_code" ]; then
  213. cookie_auth_code="drpys"
  214. fi
  215. echo -ne "${YELLOW}请输入登录用户名(30秒内无输入则使用默认值'admin'直接回车可跳过):${NC}"
  216. read -t 30 dir_path
  217. echo
  218. if [ -z "$api_auth_name" ]; then
  219. api_auth_name="admin"
  220. fi
  221. echo -ne "${YELLOW}请输入登录密码(30秒内无输入则使用默认值'drpys'直接回车可跳过):${NC}"
  222. read -t 30 dir_path
  223. echo
  224. if [ -z "$api_auth_code" ]; then
  225. api_auth_code="drpys"
  226. fi
  227. echo -ne "${YELLOW}请输入订阅PWD值(30秒内无输入则使用默认值'dzyyds'直接回车可跳过):${NC}"
  228. read -t 30 dir_path
  229. echo
  230. if [ -z "$api_pwd" ]; then
  231. api_pwd="dzyyds"
  232. fi
  233. # 使用.env.development作为模板创建.env文件,并替换自定义值
  234. cp "$env_development_path" "$env_path"
  235. if [ $? -eq 0 ]; then
  236. sed -i "s|COOKIE_AUTH_CODE = .*|COOKIE_AUTH_CODE = $cookie_auth_code|g" "$env_path"
  237. sed -i "s|API_AUTH_NAME = .*|API_AUTH_NAME = $api_auth_name|g" "$env_path"
  238. sed -i "s|API_AUTH_CODE = .*|API_AUTH_CODE = $api_auth_code|g" "$env_path"
  239. sed -i "s|API_PWD = .*|API_PWD = $api_pwd|g" "$env_path"
  240. echo -e "${GREEN}.env文件创建成功。"
  241. else
  242. echo -e "${RED}.env文件创建失败。${NC}"
  243. exit 1
  244. fi
  245. else
  246. echo -e "${YELLOW}.env文件已存在,无需创建。${NC}"
  247. fi
  248. }
  249. # 定义读取.env文件参数的函数
  250. read_env_params() {
  251. # 读取.env文件中的参数值,考虑等号前后的空格
  252. COOKIE_AUTH_CODE=$(grep '^COOKIE_AUTH_CODE' .env | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | cut -d'=' -f2)
  253. API_AUTH_NAME=$(grep '^API_AUTH_NAME' .env | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | cut -d'=' -f2)
  254. API_AUTH_CODE=$(grep '^API_AUTH_CODE' .env | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | cut -d'=' -f2)
  255. API_PWD=$(grep '^API_PWD' .env | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | cut -d'=' -f2)
  256. # 输出参数值
  257. echo -e "${QS}= 当前登录账户$API_AUTH_NAME${NC} "
  258. echo -e "${QS}= 当前登录密码$API_AUTH_CODE${NC} "
  259. echo -e "${QS}= 当前入库密码$COOKIE_AUTH_CODE${NC} "
  260. echo -e "${QS}= 当前订阅pwd值$API_PWD${NC} "
  261. }
  262. # IP显示标识
  263. has_displayed_ip=""
  264. # 显示内网和公网访问地址
  265. display_ip_addresses() {
  266. echo -e "${QS}==================================================${NC}"
  267. echo -e "${QS}= 项目主页及相关默认值提示${NC} "
  268. echo -e "${QS}= 内网访问地址:http://$LOCAL_IP:5757${NC} "
  269. # 调用read_env_params函数来显示.env中的值
  270. read_env_params
  271. echo -e "${QS}= ${YELLOW}如需修改以上密码值则自行修改源码根目录.env文件${NC} "
  272. get_device_ip
  273. if [ $? -eq 0 ]; then
  274. echo -e "${QS}= 公网主页地址:http://$IP:5757${NC}"
  275. echo -e "${QS}==================================================${NC}"
  276. else
  277. echo -e "${RED}无法获取公网IP地址。${NC}"
  278. fi
  279. }
  280. # 检查项目drpy-node是否存在
  281. if [ -d "$REPO_DIR/$PROJECT_NAME" ]; then
  282. echo -e "${YELLOW}项目drpy-node存在,跳过克隆步骤,直接执行更新脚本。${NC}"
  283. cd "$REPO_DIR/$PROJECT_NAME"
  284. else
  285. echo -e "${YELLOW}项目drpy-node不存在,正在从GitHub克隆项目...${NC}"
  286. git clone $REMOTE_REPO "$REPO_DIR/$PROJECT_NAME"
  287. if [ $? -eq 0 ]; then
  288. echo -e "${GREEN}项目drpy-node克隆成功。${NC}"
  289. cd "$REPO_DIR/$PROJECT_NAME"
  290. # 克隆后创建env.json和.env文件
  291. create_env_json "$REPO_DIR/$PROJECT_NAME"
  292. initialize_default_env "$REPO_DIR/$PROJECT_NAME" # 调用初始化.env文件的函数
  293. echo -e "${YELLOW}正在执行yarn..."
  294. yarn config set registry https://registry.npmmirror.com/
  295. yarn
  296. echo -e "${GREEN}yarn执行成功,正在启动应用...${NC}"
  297. pm2 start index.js --name drpyS
  298. pm2 save
  299. pm2 startup
  300. echo -e "${PH}尝试设置开机自动启动pm2项目,不一定成功,如果以下提示有命令请自行手动输入以确保正常开机启动${NC}"
  301. if [ -z "$has_displayed_ip" ]; then # 检查是否已经显示过IP地址
  302. display_ip_addresses
  303. has_displayed_ip=1 # 设置一个标志,表示已经显示过IP地址
  304. fi
  305. exit 1
  306. else
  307. echo -e "${RED}项目drpy-node克隆失败,请检查网络连接或仓库地址是否正确。${NC}"
  308. exit 1
  309. fi
  310. fi
  311. # 定义备份函数
  312. backup_files_and_cookie_auth_code() {
  313. # 备份前先检查文件是否存在,不存在则自动创建
  314. create_env_json "$REPO_DIR/$PROJECT_NAME"
  315. create_default_env "$REPO_DIR/$PROJECT_NAME"
  316. # 备份env.json文件
  317. local env_json_backup_file="env.json.backup_$(date +%Y%m%d).json"
  318. echo -e "${YELLOW}正在备份env.json文件...${NC}"
  319. cp "config/env.json" "./$env_json_backup_file"
  320. if [ $? -eq 0 ]; then
  321. echo -e "${GREEN}env.json文件已备份为 $env_json_backup_file${NC}"
  322. else
  323. echo -e "${RED}备份env.json文件失败。${NC}"
  324. exit 1
  325. fi
  326. # 备份.env文件
  327. local env_backup_file=".env.backup_$(date +%Y%m%d)"
  328. echo -e "${YELLOW}正在备份.env文件...${NC}"
  329. cp ".env" "./$env_backup_file"
  330. if [ $? -eq 0 ]; then
  331. echo -e "${YELLOW}.env文件已备份为 $env_backup_file${NC}"
  332. else
  333. echo -e "${RED}备份.env文件失败。${NC}"
  334. exit 1
  335. fi
  336. # 备份map.txt文件
  337. local map_txt_path="$REPO_DIR/$PROJECT_NAME/config/map.txt"
  338. local map_txt_backup_file="map.txt.backup_$(date +%Y%m%d)"
  339. echo -e "${YELLOW}正在备份map.txt文件...${NC}"
  340. cp "$map_txt_path" "./$map_txt_backup_file"
  341. if [ $? -eq 0 ]; then
  342. echo -e "${GREEN}map.txt文件已备份为 $map_txt_backup_file${NC}"
  343. else
  344. echo -e "${RED}备份map.txt文件失败。${NC}"
  345. exit 1
  346. fi
  347. # 备份parses.conf文件
  348. local parses_conf_path="$REPO_DIR/$PROJECT_NAME/config/parses.conf"
  349. local parses_conf_backup_file="parses.conf.backup_$(date +%Y%m%d)"
  350. echo -e "${YELLOW}正在备份parses.conf文件...${NC}"
  351. cp "$parses_conf_path" "./$parses_conf_backup_file"
  352. if [ $? -eq 0 ]; then
  353. echo -e "${GREEN}parses.conf文件已备份为 $parses_conf_backup_file${NC}"
  354. else
  355. echo -e "${RED}备份parses.conf文件失败。${NC}"
  356. exit 1
  357. fi
  358. }
  359. # 定义恢复函数
  360. restore_env_json_and_cookie_auth_code() {
  361. # 恢复env.json文件
  362. local env_json_backup_file="env.json.backup_$(date +%Y%m%d).json"
  363. if [ -f "./$env_json_backup_file" ]; then
  364. echo -e "${YELLOW}正在恢复env.json文件...${NC}"
  365. cp "./$env_json_backup_file" "config/env.json"
  366. if [ $? -eq 0 ]; then
  367. echo -e "${GREEN}env.json文件已恢复。${NC}"
  368. rm "./$env_json_backup_file" # 删除备份文件
  369. else
  370. echo -e "${RED}恢复env.json文件失败。${NC}"
  371. exit 1
  372. fi
  373. else
  374. echo -e "${RED}备份文件 $env_json_backup_file 不存在,无法恢复env.json文件。${NC}"
  375. exit 1
  376. fi
  377. # 恢复.env文件
  378. local env_backup_file=".env.backup_$(date +%Y%m%d)"
  379. if [ -f "./$env_backup_file" ]; then
  380. echo -e "${YELLOW}正在恢复.env文件...${NC}"
  381. cp "./$env_backup_file" ".env"
  382. if [ $? -eq 0 ]; then
  383. echo -e "${GREEN}.env文件已恢复。${NC}"
  384. rm "./$env_backup_file" # 删除备份文件
  385. else
  386. echo -e "${RED}恢复.env文件失败。${NC}"
  387. exit 1
  388. fi
  389. else
  390. echo -e "${RED}备份文件 $env_backup_file 不存在,无法恢复.env文件。${NC}"
  391. exit 1
  392. fi
  393. # 恢复map.txt文件
  394. local map_txt_backup_file="map.txt.backup_$(date +%Y%m%d)"
  395. if [ -f "./$map_txt_backup_file" ]; then
  396. echo -e "${YELLOW}正在恢复map.txt文件...${NC}"
  397. cp "./$map_txt_backup_file" "$REPO_DIR/$PROJECT_NAME/config/map.txt"
  398. if [ $? -eq 0 ]; then
  399. echo -e "${GREEN}map.txt文件已恢复。${NC}"
  400. rm "./$map_txt_backup_file" # 删除备份文件
  401. else
  402. echo -e "${RED}恢复map.txt文件失败。${NC}"
  403. exit 1
  404. fi
  405. else
  406. echo -e "${RED}备份文件 $map_txt_backup_file 不存在,无法恢复map.txt文件。${NC}"
  407. exit 1
  408. fi
  409. # 恢复parses.conf文件
  410. local parses_conf_backup_file="parses.conf.backup_$(date +%Y%m%d)"
  411. if [ -f "./$parses_conf_backup_file" ]; then
  412. echo -e "${YELLOW}正在恢复parses.conf文件...${NC}"
  413. cp "./$parses_conf_backup_file" "$REPO_DIR/$PROJECT_NAME/config/parses.conf"
  414. if [ $? -eq 0 ]; then
  415. echo -e "${GREEN}parses.conf文件已恢复。${NC}"
  416. rm "./$parses_conf_backup_file" # 删除备份文件
  417. else
  418. echo -e "${RED}恢复parses.conf文件失败。${NC}"
  419. exit 1
  420. fi
  421. else
  422. echo -e "${RED}备份文件 $parses_conf_backup_file 不存在,无法恢复parses.conf文件。${NC}"
  423. exit 1
  424. fi
  425. }
  426. # 尝试次数限制,避免无限循环
  427. MAX_ATTEMPTS=5
  428. # 尝试计数器
  429. ATTEMPT_COUNT=0
  430. # 定义git fetch最大尝试次数
  431. MAX_FETCH_ATTEMPTS=5
  432. # 尝试计数器
  433. FETCH_ATTEMPT_COUNT=0
  434. # 函数:执行git pull并检查是否成功
  435. pull_repo() {
  436. if git pull origin main; then
  437. echo -e "${GREEN}Git pull 成功。${NC}"
  438. # 执行yarn
  439. echo -e "${YELLOW}正在还原备份的文件和入库密码值${NC}"
  440. # Git pull成功后执行pm2 restart drpyS之前,还原配置文件和COOKIE_AUTH_CODE值
  441. restore_env_json_and_cookie_auth_code
  442. echo -e "${YELLOW}正在执行yarn...${NC}"
  443. if yarn; then
  444. echo -e "${GREEN}yarn执行成功。${NC}"
  445. # yarn成功后执行pm2 restart drpyS
  446. echo -e "${YELLOW}正在重启drpyS进程...${NC}"
  447. pm2 restart drpyS
  448. # 启动成功后提示项目主页访问地址
  449. if [ $? -eq 0 ]; then
  450. if [ -z "$has_displayed_ip" ]; then # 检查是否已经显示过IP地址
  451. display_ip_addresses
  452. has_displayed_ip=1 # 设置一个标志,表示已经显示过IP地址
  453. fi
  454. else
  455. echo -e "${RED}yarn执行失败。${NC}"
  456. return 1
  457. fi
  458. else
  459. echo -e "${RED}yarn执行失败。${NC}"
  460. return 1
  461. fi
  462. return 0
  463. else
  464. echo -e "Git pull 失败。"
  465. # 捕获git pull错误信息
  466. local error_output=$(git pull origin main 2>&1)
  467. # 检查是否有冲突发生
  468. if echo -e "$error_output" | grep -q 'Your local changes to the following files would be overwritten by merge:'; then
  469. echo -e "${YELLOW}检查到冲突,正在强制覆盖本地文件...${NC}"
  470. git fetch --all
  471. git reset --hard origin/main
  472. echo -e "${YELLOW}本地文件已被强制覆盖。${NC}"
  473. echo -e "${YELLOW}正在还原备份的文件和入库密码值${NC}"
  474. # Git pull成功后执行pm2 restart drpyS之前,还原配置文件和COOKIE_AUTH_CODE值
  475. restore_env_json_and_cookie_auth_code
  476. if yarn; then
  477. echo -e "${GREEN}yarn执行成功。${NC}"
  478. pm2 restart drpyS
  479. if [ $? -eq 0 ]; then
  480. if [ -z "$has_displayed_ip" ]; then # 检查是否已经显示过IP地址
  481. display_ip_addresses
  482. has_displayed_ip=1 # 设置一个标志,表示已经显示过IP地址
  483. fi
  484. else
  485. echo -e "${RED}PM2重启失败。${NC}"
  486. return 1
  487. fi
  488. else
  489. echo -e "${RED}yarn执行失败。${NC}"
  490. return 1
  491. fi
  492. else
  493. echo -e "${YELLOW}没有找到冲突文件。${NC}"
  494. echo -e "${YELLOW}$error_output${NC}"
  495. return 1
  496. fi
  497. fi
  498. }
  499. # 函数:尝试执行git fetch直到成功
  500. fetch_until_success() {
  501. local max_attempts=$MAX_FETCH_ATTEMPTS
  502. local attempt_count=0
  503. while [ $attempt_count -lt $max_attempts ]; do
  504. if git fetch origin; then
  505. echo -e "${GREEN}Git fetch 成功。${NC}"
  506. return 0
  507. else
  508. echo -e "${RED}Git fetch 失败,尝试次数:$attempt_count${NC}"
  509. ((attempt_count++))
  510. fi
  511. sleep 5 # 等待5秒后重试
  512. done
  513. echo -e "${YELLOW}已达到最大尝试次数,停止更新。${NC}"
  514. return 1 # 返回1表示失败,这样调用函数的地方可以据此判断是否需要退出循环
  515. }
  516. # 循环检查并尝试更新仓库
  517. while true; do
  518. FETCH_ATTEMPT_COUNT=0 # 重置尝试计数器
  519. ATTEMPT_COUNT=0 # 重置尝试计数器
  520. # 调用 fetch_until_success 函数,并根据返回值判断是否继续
  521. if ! fetch_until_success; then
  522. echo -e "${YELLOW}已达到最大尝试次数,停止更新。${NC}"
  523. exit 1
  524. fi
  525. # 如果git fetch成功,检查是否有更新
  526. if git status | grep -q "Your branch is behind"; then
  527. echo -e "${YELLOW}检测到有更新,执行备份文件${NC}"
  528. backup_files_and_cookie_auth_code # 调用备份函数
  529. while [ $ATTEMPT_COUNT -lt $MAX_ATTEMPTS ]; do
  530. if pull_repo; then
  531. echo -e "${GREEN}更新仓库完成"
  532. # 成功更新后不输出访问地址,直接退出循环
  533. break
  534. else
  535. # 如果git pull失败,增加尝试计数器
  536. ((ATTEMPT_COUNT++))
  537. echo -e "${RED}git pull 失败,将在 10 秒后重试(剩余尝试次数:$((MAX_ATTEMPTS - ATTEMPT_COUNT)))。${NC}"
  538. sleep 10
  539. fi
  540. done
  541. if [ $ATTEMPT_COUNT -ge $MAX_ATTEMPTS ]; then
  542. echo -e "${YELLOW}已达到最大尝试次数,停止更新。${NC}"
  543. exit 1
  544. fi
  545. else
  546. # 如果没有更新,输出访问地址
  547. if [ -z "$has_displayed_ip" ]; then # 检查是否已经显示过IP地址
  548. echo -e "${GREEN}当前仓库已经是最新的,无需更新。${NC}"
  549. display_ip_addresses
  550. has_displayed_ip=1 # 设置一个标志,表示已经显示过IP地址
  551. fi
  552. break # 退出循环
  553. fi
  554. done