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

Funkwhale 2.0.12 运维实机手册:funkwhale-manage 与 fw 两层入口、用户全生命周期含联邦删除广播、曲库导入与原位巡检、Celery 排查、PG 备份恢复实测、官方四步升级同版本演练与巡检速查。

Funkwhale音频流媒体音乐流媒体2026/10/29

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

本文是 Funkwhale 2.0.12 运维动作的实机手册:funkwhale-manage 与 fw 两层管理入口、用户全生命周期(建/改/删,含联邦删除广播实录)、曲库导入与文件巡检、Celery 异步任务排查、PostgreSQL 逻辑备份与恢复实测(恢复库校验通过后清理)、媒体目录打包、以及官方四步升级的同版本演练。全部命令与回显来自本站实例(2026-10-28 实测)。

前置阅读:部署见《Funkwhale Docker Compose 部署实战》,配置体系见《Funkwhale 配置参数详解》,定位与选型见《Funkwhale 介绍与选型指南》。

一、运维入口总览

1.1 两层命令入口

Funkwhale 的服务端管理全部通过统一入口 funkwhale-manage 完成(1.4.0 引入,2.0 延续),它本质是 Django 管理命令的分发器,另带一个面向运维的子命令族 fw:

docker exec funkwhale-2.0.12-api funkwhale-manage --help

实测输出(节选,[app] 归属清晰):

[common]
    createsuperuser
    gitpod
    inplace_to_s3
    load_test_data
    makemigrations
    migrate
    script
    testdata

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    ...
    sendtestemail
    shell
    showmigrations

[federation]
    fix_federation_ids

[music]
    check_inplace_files
    check_licenses
    create_library
    create_playlist_from_folder_structure
    fix_uploads
    generate_typesense_index
    import_files
    merge_music_data
    prune_library
    prune_non_mbid_content
    prune_skipped_uploads
    rebuild_music_permissions
    update_artist_links_and_tags

[oauth2_provider]
    cleartokens
    createapplication

[sessions]
    clearsessions

[staticfiles]
    collectstatic
    findstatic

fw 子命令族(funkwhale-manage fw --help 实测):

Commands:
  albums   Manage albums
  artists  Manage artists
  media    Manage media files (avatars, covers, attachments…)
  plugins  Manage plugins
  users    Manage users

日常分工:迁移、静态资源、曲库维护在 funkwhale-manage 根层;用户、专辑/艺术家标签、媒体缩略图在 fw 子族。

💡 技术拓展:为什么不是直接 python manage.py? Django 项目的标准入口是 manage.py,但 Funkwhale 在入口层做了定制(初始化插件依赖、校验配置等),官方从 1.4 起把 funkwhale-manage 定为唯一推荐入口——它先跑完实例级初始化再分发子命令,直接调 manage.py 会跳过这些检查。

1.2 服务进程清单与日志位置

六个服务的日志统一走 docker logs(按服务名过滤):api(Web 应用)、celery-worker(异步任务)、celery-beat(周期调度)、front(Web 服务器与访问日志)、postgres、redis。运维侧的高频排查对象是前三者。

二、用户与权限管理

2.1 创建用户:fw users create

先看用法(--help 实测):

Usage: fw users create [OPTIONS]

Options:
  -u, --username TEXT           [required]
  -p, --password TEXT           If empty, a random password will be generated
                                and displayed in console output
  -e, --email TEXT              Email address to associate with the account
                                [required]
  -q, --upload-quota INTEGER    Upload quota (leave empty to use default pod
                                quota)
  --superuser / --no-superuser
  --staff / --no-staff
  --permission TEXT
  --help                        Show this message and exit.

创建第二个超管 opsadmin(实测):

docker exec funkwhale-2.0.12-api funkwhale-manage fw users create \
  --username opsadmin --email opsadmin@funkwhale.lab \
  --password 'Ops_2026_Pass' --superuser

实测输出:

User opsadmin created!

创建后实测验证:opsadmin 通过 /api/v2/users/login 会话登录返回 200,/api/v2/auth/user/ 回显 {"pk":2,"username":"opsadmin",...}。

注意两个非交互坑(部署篇 6.5 节有完整报错):无终端环境下必须显式给 -p(缺省会进入终端取密流程,直接 Aborted!);fw users create 不支持 --no-input 参数(实测报 No such option: --no-input)。

老的 createsuperuser 在 2.0.12 已被官方拦截(实测回显原文):

CommandError: Running createsuperuser on your Funkwhale instance bypasses some of our checks which can lead to unexpected behavior of your instance. We therefore suggest to run `funkwhale-manage fw users create --superuser` instead.

2.2 修改用户:fw users set

可改属性(--help 实测节选):--active/--inactive、--superuser/--no-superuser、--staff/--no-staff、--permission-library、--permission-moderation、--permission-settings、--password、--upload-quota(由 set 支持)。

实测把临时用户 tmpuser 的上传配额设为 2048 MB:

docker exec funkwhale-2.0.12-api funkwhale-manage fw users set tmpuser \
  --upload-quota 2048 --no-input

实测输出:

Updating upload_quota on 1 matching users…
Done!

进数据库侧复核(funkwhale-manage shell 内 ORM 查询):

from funkwhale_api.users.models import User
u = User.objects.get(username='tmpuser')
print('quota:', u.upload_quota, 'active:', u.is_active, 'superuser:', u.is_superuser)

实测输出:

quota: 2048 active: True superuser: False

2.3 删除用户:fw users rm

Usage: fw users rm [OPTIONS] [USERNAME]...

Options:
  --no-input
  --hard / --no-hard  Purge all user-related info (allow recreating a user
                      with the same username)

实测硬删 tmpuser:

docker exec funkwhale-2.0.12-api funkwhale-manage fw users rm tmpuser --hard --no-input

实测输出全文(联邦侧的清理动作一览无余):

Deleting tmpuser…
2026-10-28 16:10:22,650 funkwhale_api.users.tasks INFO     Starting deletion of account tmpuser…
2026-10-28 16:10:22,674 funkwhale_api.users.tasks INFO     Deleted user object
2026-10-28 16:10:22,675 funkwhale_api.federation.tasks INFO     Broadcasting deletion to federation…
2026-10-28 16:10:22,707 funkwhale_api.federation.tasks INFO     Prepare deletion of objects associated with account tmpuser…
2026-10-28 16:10:22,736 funkwhale_api.federation.tasks INFO     Deleting 4 objects associated with account tmpuser…
2026-10-28 16:10:22,740 funkwhale_api.federation.tasks INFO     Marking actor as Tombsone…
2026-10-28 16:10:22,741 funkwhale_api.users.tasks INFO     Deletion of account done tmpuser!
  Hard delete, removing actor
  Done

要点:联邦化实例删用户不是纯本地动作——删除事件会向联邦广播,关联对象(4 个)级联清理,actor 标记为墓碑(Tombstone)。--hard 才会移除 actor 并允许同名重建;不加 --hard 的软删保留墓碑记录,联邦语义更安全。

三、曲库与文件运维

3.1 批量导入:import_files

usage: funkwhale-manage import_files [-h] [--recursive] [--username USERNAME]
                                     [--async] [--exit] [--in-place]
                                     [--replace] [--outbox] [--watch]
                                     [-e EXTENSION [EXTENSION ...]]
                                     [--broadcast] [--prune]
                                     [--reference REFERENCE] [--noinput]
                                     [--batch-size BATCH_SIZE] ...
                                     library_id path [path ...]

完整实测案例(含造文件、导入、验证)见《Funkwhale Docker Compose 部署实战》第五节,核心形态:

docker exec funkwhale-2.0.12-api funkwhale-manage import_files \
  <曲库uuid前缀> '/music/**/*.mp3' \
  --in-place --username admin --reference <自定义批次号> --noinput

运维要点:

  • --in-place 原位导入不复制文件(省磁盘),前提是 .env 配好 MUSIC_DIRECTORY_PATH/MUSIC_DIRECTORY_SERVE_PATH 双路径;
  • --async 把解析任务丢给 Celery 异步执行(大批量推荐,配合 worker 日志观察);默认同步执行,命令退出即导入完成;
  • --watch 常驻监听目录变化,适合把一个目录当「投递箱」;
  • --replace 处理重复曲目(同 MBID 或同艺术家+专辑+标题)时替换旧条目;
  • 曲库 ID 用 uuid 前缀即可(实测 a2b1e8f7 通过)。

3.2 原位文件巡检:check_inplace_files

定期验证原位导入的文件在磁盘上仍可访问(防止曲源目录被移走/权限漂移后播放 404):

docker exec funkwhale-2.0.12-api funkwhale-manage check_inplace_files

实测输出:

Checking 4 in-place imported files…
[===============---------------------------------------------] 1/4 ...
[==============================------------------------------] 2/4 ...
[=============================================---------------] 3/4 ...
[============================================================] 4/4 ...
All in-place imports have a matching on-disk file

3.3 数据修复与清理三件套

  • fix_uploads:修复已导入文件的技术元数据。参数实测:--mimetype(修正 MIME)、--audio-data(重算码率/时长,慢)、--size、--checksum、--dry-run。元数据刮削错误或换存储后先 --dry-run 看差异;
  • prune_skipped_uploads:清理「跳过」状态的导入残留。默认 dry-run,加 --force 才真删(--help 实测原文:Disable dry run mode and apply pruning for real);
  • prune_library / prune_non_mbid_content:整库级清理,动作重,执行前务必备份(第五节)。

3.4 缩略图与标签工具

fw media generate-thumbnails:为全部头像/封面重建缩略图(官方升级说明里 2.x 迁移后的推荐动作)。fw albums add-tags-from-tracks / fw artists add-tags-from-tracks:把曲目级流派标签回填到无标签的专辑/艺术家。

四、Celery 异步任务排查

4.1 worker 与 beat 的分工

worker 执行任务,beat 只负责按调度表派发周期任务。beat 启动日志(实测头部):

+ exec celery '--app=funkwhale_api.taskapp' beat '--loglevel=info'
celery beat v5.6.2 (recovery) is starting.

beat 派发的周期任务在 worker 日志里形成稳定的节拍(实测节选):

Task common.prune_unattached_attachments[96c18c88-...] succeeded in 0.0227s
Task audio.fetch_rss_feeds[5cd11706-...] succeeded in 0.0176s
Task federation.refresh_nodeinfo_known_nodes[8a77c33-...] succeeded in 0.0141s

附件清理、RSS 源刷新、nodeinfo 刷新都是自动节奏,worker 停机超过节拍间隔时这些任务会堆积,恢复后自动补跑。

4.2 探活与活动视图

docker exec funkwhale-2.0.12-celery-worker celery --app=funkwhale_api.taskapp inspect ping

实测输出:

->  celery@766fb18e07c1: OK
        pong

1 node online.
docker exec funkwhale-2.0.12-celery-worker celery --app=funkwhale_api.taskapp inspect active

实测输出:

->  celery@766fb18e07c1: OK
    - empty -

1 node online.

排查套路:ping 确认 worker 存活 → active 看正在执行的任务 → docker logs funkwhale-2.0.12-celery-worker 追任务级日志 → 结合 --reference 批次号定位导入轨迹。

4.3 任务成功样例:导入链路

一次界面/CLI 导入在 worker 日志里的完整形态(实测):

2026-10-28 15:44:30,439 funkwhale_api.music.tasks INFO     [Album 1] scanning covers from /music
[2026-10-28 15:44:30,475: WARNING/ForkPoolWorker-2] Successfully imported 3 new tracks in 0s
[2026-10-28 15:44:30,475: WARNING/ForkPoolWorker-2] For details, please refer to import reference 'fs-import-001' or URL http://funkwhale.lab/library/a2b1e8f7-.../upload?import=fs-import-001
[2026-10-28 15:44:30,476: INFO/ForkPoolWorker-2] Task music.fs_import[e3a3816f-...] succeeded in 0.1978s

任务名、执行线程、耗时、批次引用号四要素齐全——导入「卡住」时先看这里有没有对应 reference 的任务行。

五、数据库备份与恢复实测

5.1 全库逻辑备份

mkdir -p /opt/data/quzuo/tmp/funkwhale/stack/backup
docker exec funkwhale-2.0.12-postgres pg_dump --username=funkwhale --dbname=funkwhale \
  | gzip > /opt/data/quzuo/tmp/funkwhale/stack/backup/fw_db_$(date +%Y%m%d).sql.gz

实测产物与校验:

-rw-r--r-- 1 root root 41436 Oct 29 00:08 fw_db_20261029.sql.gz    # gzip 压缩后
gunzip -t fw_db_20261029.sql.gz && echo 'gzip integrity OK'         # 完整性 OK

纯文本 dump 共 8530 行(本实例 4 曲目/2 用户规模,大库按比例放大)。升级前必做(第六节),建议 cron 每日一份。

5.2 恢复实测:还原到独立库并校验

恢复演练不碰生产库——先建一个独立恢复库,把备份灌进去验证内容完整性:

docker exec funkwhale-2.0.12-postgres createdb --username=funkwhale --owner=funkwhale funkwhale_restore
gunzip -c fw_db_20261029.sql.gz | docker exec -i funkwhale-2.0.12-postgres \
  psql --username=funkwhale --dbname=funkwhale_restore --set ON_ERROR_STOP=1

实测尾部输出:

ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE

一致性校验(对照生产库的 4 曲目 / 2 用户 / 236 条迁移):

SELECT (SELECT count(*) FROM music_track) AS tracks,
       (SELECT count(*) FROM users_user)  AS users,
       (SELECT count(*) FROM django_migrations) AS migrations;

实测输出:

 tracks | users | migrations
--------+-------+------------
      4 |     2 |        236
(1 row)

用户表逐行核对(admin 与 opsadmin 及超管标记原样保留)后,清理演练库:

docker exec funkwhale-2.0.12-postgres dropdb --username=funkwhale --if-exists funkwhale_restore

实测输出:dropdb OK。真机故障恢复的完整动作即:空库重建(或数据目录重置后由编排自动初始化同名库)→ 灌 dump → funkwhale-manage migrate 对齐迁移账本 → 重启服务。

5.3 媒体与音乐目录打包

数据库之外的两块状态:MEDIA_ROOT(上传/缩略图)与 MUSIC_DIRECTORY_SERVE_PATH(原位曲源)+ STATIC_ROOT(静态资源,可随时由 collectstatic 重建,顺手一起打包成本极低):

tar czf backup/fw_media_music_$(date +%Y%m%d).tar.gz -C data media music static

实测产物:fw_media_music_20261029.tar.gz,1270012 字节。原位导入的实例尤其要注意:数据库里的曲目行指向 file:///music/...,只有数据库备份而没有音乐目录备份,恢复出来的是一座空图书馆。

六、升级实战:官方四步 + 同版本演练

6.1 官方标准流程

docs.funkwhale.audio《Upgrade your Docker Funkwhale installation》给出的步骤(根 shell 下):

source .env                     # 载入环境变量
docker compose pull             # 拉取新版服务版本
docker compose run --rm api funkwhale-manage migrate   # 应用数据库迁移
docker compose up -d            # 重建全部服务
exit

升级前的两道保险(结合官方 2.0.0 发布博客的强调):

  1. 完整备份:5.1 + 5.3 的产物(官方原话:迁移过程被打断有数据丢失风险);
  2. 查 changelog 手工动作:跨大版本必有手工步骤——1.4→2.x 必须直接升到 2.0.4 以上、2.0.3 起补数据库三变量、升级后重建缩略图(fw media generate-thumbnails)。

6.2 同版本演练实测

以 2.0.12 原地走一遍四步(等价于真升级的完整路径,风险为零):

docker compose pull

实测输出(节选):

 Image postgres:15-alpine Pulled
 Image redis:7-alpine Pulled
 Image funkwhale/front:2.0.12 Pulled
 Image funkwhale/api:2.0.12 Pulled
docker compose run --rm api funkwhale-manage migrate

实测输出全文:

Operations to perform:
  Apply all migrations: account, admin, audio, auth, authtoken, common, contenttypes, dynamic_preferences, favorites, federation, history, moderation, music, playlists, portability, radios, requests, sessions, sites, socialaccount, tags, users
Running migrations:
  No migrations to apply.
docker compose up -d

实测输出(节选):

 Container funkwhale-2.0.12-celery-beat Started
 Container funkwhale-2.0.12-api Started
 Container funkwhale-2.0.12-front Started

演练后复核:nodeinfo 版本 2.0.12、tracks 计数不变、listen 流 200——升级动作对数据零影响。真版本升级只多两件事:改 .env 的 FUNKWHALE_VERSION 再 pull,以及按 changelog 补手工步骤。

七、日常巡检与排障速查

7.1 一分钟巡检脚本

# 1) 实例身份与版本
curl -s http://127.0.0.1:8140/api/v1/instance/nodeinfo/2.0/ | python3 -c "import json,sys; print(json.load(sys.stdin)['software'])"
# 2) worker 存活
docker exec funkwhale-2.0.12-celery-worker celery --app=funkwhale_api.taskapp inspect ping
# 3) 服务状态
docker compose ps
# 4) 原位文件完好性
docker exec funkwhale-2.0.12-api funkwhale-manage check_inplace_files

本实例的基准值:版本 2.0.12、1 node online、六服务 Up、4/4 原位文件完好。

7.2 高频问题速查

症状首查点实测依据
登录后跳转异常users:redirect 悬空引用(无法经 .env 修正),走 Web 界面登录部署篇 6.1 节
管理后台无样式collectstatic 是否执行过部署篇 3.2 节(174 文件补课后恢复)
上传报 413NGINX_MAX_BODY_SIZE,改后需重建 front配置篇 3.2 节(50M 改值实测)
导入命令卡住退出非交互环境缺 --noinput / -p部署篇 6.5 节(EOFError 实录)
播放 404(原位曲库)check_inplace_files + /_protected/music/ 路径对齐配置篇 3.3 节
任务不执行inspect ping → beat 是否存活 → worker 日志本文 4.2/4.3 节
升级后功能异常迁移是否跑完(showmigrations)、changelog 手工步骤本文 6.1/6.2 节

信息来源:全部命令与回显来自 2026-10-28 本站实例实测(Funkwhale api/front 2.0.12 发行版);官方升级流程引自 docs.funkwhale.audio《Upgrade your Docker Funkwhale installation》(查询日期 2026-10-28);createsuperuser 拦截、联邦删除广播、Celery 周期任务等行为均为实机捕获。