小白式一键更新 serv00 上部署的 new-api 版本
参考了 @Reno 佬的更新脚本进行了优化
需要 github 令牌,否则会出现”403 Client Error: rate limit exceeded
,当前 GitHub API 请求超出了速率限制 “ 问题
#!/usr/local/bin/python
import os
import requests
import subprocess
import logging
import json
from datetime import datetime, timedelta
import time
# 用户配置项
USERNAME = '' # 用户名
DOMAIN = '' # 域名
WORK_DIR = f'/home/{USERNAME}/domains/{DOMAIN}/public_html' # 工作目录
LOG_FILE = f'/home/{USERNAME}/domains/update.log' # 日志文件路径
GITHUB_PROJECT = 'k0baya/new-api-freebsd' # GitHub 项目路径
GITHUB_TOKEN = '' # GitHub 访问令牌
# 配置日志记录
logging.basicConfig (filename=LOG_FILE, level=logging.INFO, format='%(asctime) s %(levelname) s:%(message) s')
def get_latest_release ():
"""
获取最新版本信息。首先尝试从缓存文件读取,如缓存无效则调用 GitHub API 获取最新版本。
返回包含版本信息的字典。
"""
cache_file = f"{WORK_DIR}/latest_release.json" # 缓存文件路径
# 尝试从缓存文件中读取版本信息
try:
if os.path.exists (cache_file):
cache_time = datetime.fromtimestamp (os.path.getmtime (cache_file))
if datetime.now () - cache_time < timedelta (hours=1): # 缓存有效期为 1 小时
with open (cache_file, "r") as f:
return json.load (f)
except Exception as e:
logging.error (f"Error reading cache: {e}")
# 如果缓存无效,调用 GitHub API 获取最新版本信息
try:
headers = {"Authorization": f"token {GITHUB_TOKEN}"} # 使用 GitHub 访问令牌
url = f"https://api.github.com/repos/{GITHUB_PROJECT}/releases/latest"
response = requests.get (url, headers=headers)
response.raise_for_status () # 检查请求是否成功
release = response.json ()
# 将新版本信息写入缓存文件
with open (cache_file, "w") as f:
json.dump (release, f)
return release
except Exception as e:
logging.error (f"Error fetching release: {e}")
return None
def download_asset (url, dest_path):
"""
下载指定 URL 的资源到目标路径 dest_path。
返回 True 表示下载成功,False 表示下载失败。
"""
try:
with requests.get (url, stream=True, timeout=10) as r:
r.raise_for_status () # 检查请求是否成功
with open (dest_path, 'wb') as f:
for chunk in r.iter_content (chunk_size=8192):
f.write (chunk) # 写入文件
logging.info (f"Downloaded asset to {dest_path}")
return True
except requests.exceptions.RequestException as e:
logging.error (f"Download failed: {e}")
return False
def update_service ():
"""
更新服务到最新版本。获取最新版本信息,下载并替换文件,重启服务。
"""
try:
release = get_latest_release () # 获取最新版本信息
if not release:
logging.error ("Failed to get release info")
return
# 获取最新版本的可下载 URL
asset_url = next ((asset ['browser_download_url'] for asset in release.get ('assets', []) if asset ['name'] != 'source code'), None)
if not asset_url:
logging.error ("No asset URL found")
return
# 下载新版本文件到临时文件
temp_file_path = f"{WORK_DIR}/newapi_temp"
final_file_path = f"{WORK_DIR}/newapi"
if not download_asset (asset_url, temp_file_path):
logging.error ("Asset download failed")
return
# 设置临时文件的执行权限
subprocess.run (["chmod", "+x", temp_file_path], check=True)
# 停止服务
subprocess.run ([f"killall", "-u", f"{USERNAME}"], check=True)
time.sleep (2) # 等待进程完全停止
# 替换旧版本
if os.path.exists (final_file_path):
os.remove (final_file_path) # 删除旧版本文件
os.rename (temp_file_path, final_file_path) # 重命名临时文件为最终文件
# 重启服务
subprocess.run ([f"/home/{USERNAME}/.npm-global/bin/pm2", "resurrect"], check=True)
# 写入更新的版本信息到文件
with open (f"{WORK_DIR}/read.me", "w") as file:
file.write (f"Version: {release ['tag_name']}\n")
logging.info (f"Updated to version {release ['tag_name']}")
except Exception as e:
logging.error (f"Error during update process: {e}")
if __name__ == "__main__":
update_service () # 手动执行一次更新
在 ~/domains
目录下创建 update.py
后,填写里面的配置,在对应目录运行 py。如果需要定时检查,自己创建 cron 任务就行。
Github 访问令牌
注意其中的文件命名
更新后,注意修改 start.sh 的文件名,启动即可
export TIKTOKEN_CACHE_DIR="/usr/home/ 用户名 /domains/ 自己域名 /public_html"
# 把下一行的 PORT 改为自己放行的端口
exec ./newapi_temp --port xxx --log-dir ./logs