pyLoad 常用命令与运维实战(核心篇)

pyLoad(pyload-ng)命令与运维核心篇:pyload CLI 参数全表与 dry-run 实测回显、REST API 三层认证体系与全流程真实回显(登录/API key/加包/队列/配置/服务调用)、插件管理、配置与下载备份恢复及六条排障实录。

pyLoad下载管理器NAS 自托管电子表格2026/10/28

pyLoad 常用命令与运维实战(核心篇)

目标:给运维者一份"拿起来就能用"的 pyLoad(pyload-ng)核心操作手册:pyload CLI 的参数全表与实测回显、REST API 的认证体系与全流程真实回显(登录、API key、添加包、队列控制、配置读写、服务调用)、插件管理实操、配置与下载目录的备份恢复,以及本次实测沉淀的排障实录。所有命令与回显均来自 2026-10-28 真实容器实测(pyload-ng 0.5.0b3.dev101);部署与配置基础见本专栏《pyLoad Docker Compose 部署实战》《pyLoad 配置参数详解》。

一、环境信息

项目实测值
pyLoad 版本pyload-ng 0.5.0b3.dev101(CLI 版本串 pyLoad 0.5.0)
运行形态容器(linuxserver/pyload-ng),WebUI 宿主端口 8133 → 容器 8000
实测地址http://127.0.0.1:8133(宿主侧 curl)
实测账号默认账号 pyload / pyload(演示环境;生产务必改密)
下载目录/downloads(容器内),对应宿主 bind mount
REST API 规范GET /api/openapi.json(84 个路径端点,实测统计)

二、pyload CLI 速查

2.1 版本与帮助(实测回显)

pyload --version
# 实测回显:
# pyLoad 0.5.0

pyload --help
# 实测回显(banner 之外全文):
# usage: pyload [-h] [-d] [-r] [--storagedir STORAGEDIR] [--userdir USERDIR]
#               [--tempdir TEMPDIR] [--pidfile PIDFILE] [--dry-run] [--daemon]
#               [--quit] [--status] [--generate-api-spec] [--version]
#
# The free and open-source Download Manager written in pure Python
#
# options:
#   -h, --help            show this help message and exit
#   -d, --debug           enable debug mode
#   -r, --reset           reset default username/password
#   --storagedir STORAGEDIR
#                         use this location to save downloads
#   --userdir USERDIR     use this location to store user data files
#   --tempdir TEMPDIR     use this location to store temporary files
#   --pidfile PIDFILE     set the full path to the pidfile
#   --dry-run             test start-up and exit
#   --daemon              run as daemon
#   --quit                stop a running pyLoad instance
#   --status              get status of a running pyLoad instance
#   --generate-api-spec   save the api specification to file
#   --version             show program's version number and exit

2.2 参数逐条实测说明

参数实测要点
--storagedir / --userdir / --tempdir三类目录重定向(下载/用户数据/临时)。容器镜像即用 --userdir /config --storagedir /downloads 落到挂载点;裸机默认 ~/Downloads/pyLoad、~/.pyload、<TMPDIR>/pyLoad。实测传自定义目录后启动日志明确回显 User directory: /tmp/duser
--pidfilepid 文件路径。实测要点:已有实例运行时再起进程会直接退出(pyLoad already running with pid 5225),多实例共存必须给各自独立 pidfile
--dry-run启动自检后退出,exit=0。实测回显含 *** TEST RUN ***、插件索引、Activated addons: ... / Deactivate addons: ... 全量清单,是验证目录权限与插件激活状态的快速手段
--daemon守护进程化(配合 systemd 时建议直接前台运行让 systemd 托管)
--quit / --status停止/查询运行中实例(读取 pidfile 定位)
--generate-api-spec把 OpenAPI 规范落盘为本地文件(离线生成客户端用)
-r / --reset重置用户名/密码(忘记口令时的救援通道,实测配置篇有对应排障)
-d / --debug调试模式(等价于配置 general.debug_mode)

--dry-run 实测关键回显(2026-10-28,截取):

[2026-10-28 12:51:17]  INFO  pyload  *** Welcome to pyLoad 0.5.0 ***
[2026-10-28 12:51:17]  INFO  pyload  *** TEST RUN ***
[2026-10-28 12:51:17]  INFO  pyload  Activated addons: ExternalScripts, NZB, TORRENT, UnSkipOnFail, UserAgentSwitcher
[2026-10-28 12:51:17]  INFO  pyload  User directory: /tmp/duser
[2026-10-28 12:51:17]  INFO  pyload  Cache directory: /tmp/pyLoad

三、REST API 认证体系(实测结论)

pyLoad 0.5.0b3 的 API 有三层认证,权限边界实测如下,这直接决定你的调用姿势:

层级方式实测权限边界
1HTTP Basic(-u pyload:pyload)只读够用:GET /api/openapi.json、GET /api/status_server、GET /api/get_queue 等查询全部可过;写操作被拒({"error": "Invalid API credentials"})
2会话 Cookie(WebUI 登录)全权限,但 POST 需带 CSRF token(从 /login 页 csrf_token 隐藏域提取,header 名 X-CSRFToken)
3X-API-Key 请求头全权限 + 无 CSRF 负担,脚本运维首选。key 存于 pyload.db 的 apikeys 表(哈希)

实测推荐:脚本一律走第 3 层。获取 API key 的完整实测流程:

# 1) 登录拿会话 + CSRF(实测登录成功回显 302)
curl -s -c cookies.txt http://127.0.0.1:8133/login -o login.html
TOKEN=$(grep -oE 'name="csrf_token" value="[^"]*"' login.html | head -1 | sed 's/.*value="//;s/"$//')
curl -s -b cookies.txt -c cookies.txt -X POST http://127.0.0.1:8133/login \
  -d "username=pyload&password=pyload&csrf_token=$TOKEN" \
  -o /dev/null -w 'login_http=%{http_code}\n'
# 实测回显:login_http=302

# 2) 生成 API key(JSON body,注意不要混入 csrf_token 字段——见排障实录 2)
curl -s -b cookies.txt -X POST http://127.0.0.1:8133/json/generate_apikey \
  -H 'Content-Type: application/json' \
  -d '{"user":"pyload","password":"pyload","name":"cli-test","expires":0}'
# 实测回显:
# {"success": true, "data": {"key": "HO2gbT7S7tqszsBE6l2E5vH0lB2hcSLyXy7Z4wJGCSX0YF1iXZ6WdXxXtX9XtX6G", "name": "cli-test", "expires": 0, "id": 2}}

# 3) 之后所有脚本调用带 X-API-Key 头
KEY=$(python3 -c "import json;print(json.load(open('apikey.json'))['data']['key'])")

四、API 全流程实战(真实回显)

4.1 投递下载包与查队列

# 添加包(返回新包 pid)
curl -s -H "X-API-Key: $KEY" -X POST http://127.0.0.1:8133/api/add_package \
  -H 'Content-Type: application/json' \
  -d '{"name":"demo-pack","links":["https://codeload.github.com/pyload/pyload/zip/refs/heads/stable"],"dest":1}'
# 实测回显:8

dest 取值实测:1 = 队列(Queue),0 = 收集器(Collector)。任务先入 Collector,再"推入队列"是 WebUI 的默认交互;脚本直投用 dest:1。

# 查队列(实测返回包对象数组)
curl -s -H "X-API-Key: $KEY" http://127.0.0.1:8133/api/get_queue | python3 -m json.tool | head -20
# 实测回显(截取):
# [
#     {
#         "id": 8,
#         "name": "demo-pack",
#         "linksdone": 1,
#         "linkstotal": 1,
#         "sizetotal": 22400000,
#         "sizedone": 22400000,
#         "status": 2,
#         ...
#     }
# ]

# 全局状态(暂停/活跃/队列数/速度)
curl -s -H "X-API-Key: $KEY" http://127.0.0.1:8133/api/status_server
# 实测回显:
# {"pause": false, "active": 0, "queue": 1, "total": 4, "speed": 0, "download": true, "reconnect": false, "captcha": false, "proxy": false}

4.2 队列控制

操作端点(实测存在)说明
暂停/恢复切换POST /api/toggle_pause返回切换后的暂停态
全停当前下载POST /api/stop_all_downloads停止活跃任务,不删包
重启失败包POST /api/restart_package对失败包重投
清理已完成包POST /api/delete_finished一键清空 finished 包
删除指定包POST /api/delete_packages,body {"package_ids":[7,8]}参数名是 package_ids(实测:误传 pids 会静默失败)
手动触发解包POST /api/service_call,body {"service_name":"ExtractArchive.extract_package","arguments":[7]}service 名 = 插件名.方法;arguments 是纯参数数组(实测传 dict 会污染持久化队列,见排障实录 4)

4.3 配置读写(与配置篇互证)

curl -s -H "X-API-Key: $KEY" 'http://127.0.0.1:8133/api/get_config_value?category=webui&option=port&section=core'
# 实测回显:8000

curl -s -H "X-API-Key: $KEY" -X POST http://127.0.0.1:8133/api/set_config_value \
  -H 'Content-Type: application/json' \
  -d '{"category":"download","option":"max_speed","value":512,"section":"core"}'
# 实测回显:null   (即写即落盘)

section 取值:core(pyload.cfg)/ plugin(plugins.cfg)/ account(accounts.cfg)。

4.4 服务与进程管理

# 调用插件暴露的服务(@expose 方法)
curl -s -H "X-API-Key: $KEY" -X POST http://127.0.0.1:8133/api/service_call \
  -H 'Content-Type: application/json' \
  -d '{"service_name":"ExtractArchive.extract_package","arguments":[7]}'
# 实测回显:"None"   (异步触发成功)

# 重启核心(实测:必须不带请求体!)
curl -s -H "X-API-Key: $KEY" -X POST http://127.0.0.1:8133/api/restart
# 实测回显:null

重启后需等待核心就绪(实测约 10–15 秒),过早调用写端点会得到 {"error": "Invalid API credentials"}(认证缓存未就绪的表象,等一下重试即可)。

五、插件管理实战

5.1 查看插件清单与激活状态

curl -s -H "X-API-Key: $KEY" http://127.0.0.1:8133/api/get_plugin_config | python3 -c "
import sys, json
d = json.load(sys.stdin)
print('plugins:', len(d))
print('ExtractArchive:', d.get('ExtractArchive'))
"
# 实测回显(截取):
# plugins: 339
# ExtractArchive: {'enabled': True, 'delete': True, ...}

日志侧的插件版本与后端探测(restart 后实测逐行):

[2026-10-28 12:38:35]  INFO  pyload  Activated addons: ExternalScripts, ExtractArchive, NZB, TORRENT, UnSkipOnFail, UserAgentSwitcher
[2026-10-28 12:38:35]  DEBUG pyload  ADDON ExtractArchive: Found HjSplit 0.03 | Found UnRar 7.23 | Found SevenZip 24.09 | Found UnZip 3.12.15 | Found UnTar 3.12.15

5.2 激活/停用插件(以解包链为例)

pyLoad 没有 enable/disable 专用 REST 端点(实测 enable_plugin 404),激活开关就是各插件配置节的 enabled:

# 激活解包总开关与 zip 适配器(section=plugin)
for pair in 'ExtractArchive' 'UnZip'; do
curl -s -H "X-API-Key: $KEY" -X POST http://127.0.0.1:8133/api/set_config_value \
  -H 'Content-Type: application/json' \
  -d "{\"category\":\"$pair\",\"option\":\"enabled\",\"value\":true,\"section\":\"plugin\"}"; echo
done
# 实测回显:null null   (即时落盘;插件加载在下次 restart 后刷新)

实测注意:配置即时生效,但插件运行时加载发生在进程重启时——改 enabled 后需 POST /api/restart 才能观察到 Activated addons 变化。

5.3 插件更新

插件随包发布(pip 装的 pyload-ng 内置 339 个),0.5.0b3 阶段没有官方"一键更新插件"通道:升级 = 升级 pyload-ng 包 / 更换镜像 tag。容器形态下 docker compose pull && docker compose up -d 即完成插件集更新;手改容器内插件源码的补丁(如部署篇 UnZip bug 修复)在镜像更新后会被覆盖,需重新评估是否还需要。

六、备份与恢复(实测)

6.1 备份什么

内容路径实测体量说明
配置/config/24 个文件,tar.gz 后 2.1 MiBpyload.cfg、plugins.cfg、accounts.cfg、pyload.db、日志、回收站
下载产物/downloads/17 MiB(实测样例数据),tar.gz 后 8.4 MiB按需;重下载成本高的大文件建议备份

实测命令(容器宿主侧,bind mount 路径):

cd /opt/data/pyload
tar czf pyload-config-backup-$(date +%Y%m%d).tar.gz config/
tar czf pyload-downloads-backup-$(date +%Y%m%d).tar.gz downloads/
# 实测产物:
# pyload-config-backup-20261028.tar.gz   2.1M
# pyload-downloads-backup-20261028.tar.gz 8.4M

严谨流程建议先停服再打包(避免打包瞬间 db 正在写入):docker compose stop pyload → 打包 → docker compose start pyload。实测补充:pyload.db 属 SQLite 单文件,运行中直接 sqlite3 .backup 亦可,但 tar 整目录最简单可靠。

6.2 恢复

docker compose stop pyload
rm -rf config/ downloads/          # 或 mv 走旧目录
tar xzf pyload-config-backup-20261028.tar.gz
tar xzf pyload-downloads-backup-20261028.tar.gz
chown -R 1000:1000 config downloads  # 与 PUID/PGID 对齐
docker compose start pyload

恢复后验证三件事(实测口径):/api/status_server 正常回显、队列包完整(get_queue 包数与备份前一致)、API key 仍有效(key 在 pyload.db 的 apikeys 表,随配置备份一起恢复)。

七、排障实录(实测沉淀)

  1. 写操作报 Invalid API credentials 但只读正常:HTTP Basic 只有查询权限(本文第三节实测边界),写操作必须 X-API-Key 或会话。先检查调用层级再怀疑密码。

  2. generate_apikey 报 500(TypeError: unexpected keyword argument):/json/* 端点把 JSON body 字段直接映射为函数参数,body 里混入 csrf_token 等非参数字段就会炸。实测结论:/json/generate_apikey 只收 user/password/name/expires 四个字段;CSRF 只走 header。

  3. /api/restart 带 body 报 500:body 会被当 kwargs 透传,Api.restart() 不接受参数。裸 POST 即可(实测回显 null)。

  4. 解包线程"锁死",重启也不恢复:手动 service_call 传错参数(如把 dict 塞进 arguments)后,坏条目持久化在 pyload.db 的 storage 表(identifier='ExtractArchive', key='Queue'),每次启动 resume 都炸掉解包线程,且 extracting 标志异常后不复位。实测解法:停服删坏队列行 + 重启——

    docker exec pyload-050b3-webui python3 -c "
    import sqlite3
    con = sqlite3.connect('/config/data/pyload.db')
    con.execute(\"DELETE FROM storage WHERE identifier='ExtractArchive' AND key='Queue'\")
    con.commit()"
    docker restart pyload-050b3-webui
    
  5. 重启后 API 调用突然全部 Invalid credentials:核心未就绪(实测重启后 10–15 秒内),等待重试即可,不是 key 丢了。

  6. delete_packages 不生效:body 参数名是 package_ids(复数全称),实测传 pids 不报错但什么都不删——这类"静默失败"建议每次删完用 get_queue 核对。

八、参考链接