pyLoad 常用命令与运维实战(核心篇)
pyLoad(pyload-ng)命令与运维核心篇:pyload CLI 参数全表与 dry-run 实测回显、REST API 三层认证体系与全流程真实回显(登录/API key/加包/队列/配置/服务调用)、插件管理、配置与下载备份恢复及六条排障实录。
pyLoad 常用命令与运维实战(核心篇)
目标:给运维者一份"拿起来就能用"的 pyLoad(pyload-ng)核心操作手册:
pyloadCLI 的参数全表与实测回显、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 |
--pidfile | pid 文件路径。实测要点:已有实例运行时再起进程会直接退出(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 有三层认证,权限边界实测如下,这直接决定你的调用姿势:
| 层级 | 方式 | 实测权限边界 |
|---|---|---|
| 1 | HTTP 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) |
| 3 | X-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§ion=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 MiB | pyload.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 表,随配置备份一起恢复)。
七、排障实录(实测沉淀)
-
写操作报
Invalid API credentials但只读正常:HTTP Basic 只有查询权限(本文第三节实测边界),写操作必须X-API-Key或会话。先检查调用层级再怀疑密码。 -
generate_apikey报 500(TypeError: unexpected keyword argument):/json/*端点把 JSON body 字段直接映射为函数参数,body 里混入csrf_token等非参数字段就会炸。实测结论:/json/generate_apikey只收user/password/name/expires四个字段;CSRF 只走 header。 -
/api/restart带 body 报 500:body 会被当 kwargs 透传,Api.restart()不接受参数。裸 POST 即可(实测回显null)。 -
解包线程"锁死",重启也不恢复:手动
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 -
重启后 API 调用突然全部 Invalid credentials:核心未就绪(实测重启后 10–15 秒内),等待重试即可,不是 key 丢了。
-
delete_packages 不生效:body 参数名是
package_ids(复数全称),实测传pids不报错但什么都不删——这类"静默失败"建议每次删完用get_queue核对。
八、参考链接
- 部署与镜像事实:《pyLoad Docker Compose 部署实战》
- 配置体系:《pyLoad 配置参数详解》
- 选型与生态:《pyLoad 介绍与选型指南》
- OpenAPI 规范(运行实例自描述):
http://<pyLoad地址>:8000/api/openapi.json - 官方源码(API 定义:
src/pyload/core/api/__init__.py):https://github.com/pyload/pyload