Prosody IM 13.0.7 常用 CLI 命令详解

prosodyctl 13.0.7 全量子命令实测详解:status/version/about/check、adduser/passwd/deluser、cert 证书五子命令、社区插件 install/list/remove,以及 shell 管理控制台 user/module/c2s/s2s/muc/config/stats 等全部分区命令的真实回显、在线会话实测与 8 条排障实录。

Prosody IM即时通信Prosody IM2026/10/21

Prosody IM 13.0.7 常用 CLI 命令详解

目标:逐条实测 Prosody IM 13.0.7 管理命令行工具 prosodyctl 的全部子命令——服务状态、用户管理、证书管理、社区插件管理,以及内置管理控制台(shell)各分区命令,每条命令均给出真实执行回显与边界行为。已在 Ubuntu 22.04 + Prosody 13.0.7(安装方法见 《Ubuntu 22.04 安装 Prosody IM 13.0.7 指南》)实测通过,全部命令与回显均为真实执行记录。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64);
  • 软件版本:Prosody IM 13.0.7(包版本 13.0.7-1~jammy2),systemd 托管;
  • 示例 XMPP 域名:xmpp.example.com,MUC 组件域名:chat.example.com;
  • 示例管理员:admin@xmpp.example.com,密码 q1w2e3r4;
  • 关键路径:数据 /var/lib/prosody/、日志 /var/log/prosody/、证书 /etc/prosody/certs/、模块 /usr/lib/prosody/modules/;
  • 相关文档:《Prosody IM 13.0.7 配置参数详解》(配置文件参数)、《Prosody IM 13.0.7 介绍与选型指南》(架构与选型)。

二、工具概览

2.1 prosodyctl 在管理工具体系中的定位

Prosody 13.0.7 的日常管理有四条通道,prosodyctl 是其中唯一的服务器本地命令行入口:

通道形态适用场景
prosodyctl <子命令>本地 CLI,一次性执行用户增删、证书、插件安装、状态检查
prosodyctl shell本地控制台(可交互、可单次执行)会话管理、模块热加载、房间管理、实时诊断
systemd(systemctl)服务托管层启停服务、开机自启、日志查看
XMPP ad-hoc 命令客户端内管理有管理客户端时的远程管理(需 admin_adhoc 模块)

💡 说明:prosodyctl 与 systemctl 分工明确——服务的启停、开机自启由 systemd 托管(systemctl start/stop/restart prosody),而 prosodyctl 负责服务器内容层面的管理(账号、证书、插件、诊断)。prosodyctl 自带的 reload 只重载配置,服务进程仍由 systemd 管理。

2.2 主命令清单

prosodyctl --help 实测全量输出:

Danger, Will Robinson! Prosody doesn't need to be run as root, so don't do it!
For more information on running Prosody as root, see https://prosody.im/doc/root
prosodyctl - Manage a Prosody server

Usage: /usr/bin/prosodyctl COMMAND [OPTIONS]

Where COMMAND may be one of:

Process management:
 reload            Reload Prosody's configuration and re-open log files
 status            Reports the running status of Prosody
 shell             Interact with a running Prosody

User management:
 adduser JID       Create the specified user account in Prosody
 passwd JID        Set the password for the specified user account in Prosody
 deluser JID       Permanently remove the specified user account from Prosody

Plugin management:
 install           Installs a prosody/luarocks plugin
 remove            Removes a module installed in the working directory's plugins folder
 list              Shows installed rocks

Informative:
 check             Perform basic checks on your Prosody installation
 version [-v]      Show current Prosody version, or more

Other:
 cert              Certificate management commands
 about             Show information about this Prosody installation

首行 "Danger, Will Robinson!" 是因为以 root 身份执行了 prosodyctl --help:Prosody 提示自身无需 root 运行(服务以 prosody 用户跑)。该提示只是提醒,不影响命令执行;用户管理等写操作需要 root 或 sudo。

主命令与章节对应关系:

分组命令详解位置
Processreload / status / shell第四章、第六章
Useradduser / passwd / deluser第五章
Plugininstall / remove / list第八章
Informativecheck / version第四章
Othercert / about第七章、第四章

2.3 管理控制台命令地图

prosodyctl shell 进入交互式管理控制台,也支持把命令直接作为参数一次执行(本文实测均用一次执行形态:prosodyctl shell <命令>)。控制台内 help 列出全部 22 个命令分区(实测):

Commands are divided into multiple sections. For help on a particular section,
type: help SECTION (for example, 'help c2s'). Sections are:

Section  | Description
c2s      | Commands to manage local client-to-server sessions
config   | Reloading the configuration, etc.
cron     | View and manage recurring tasks
debug    | Commands for debugging the server
dns      | Commands to manage and inspect the internal DNS resolver
help     | Show this help about available commands
host     | Commands to activate, deactivate and list virtual hosts
http     | Commands to inspect HTTP services
invite   | Create and manage invitations
limits   | Commands to inspect rate-limiting state
migrate  | Perform data migrations
module   | Commands to load/reload/unload modules/plugins
muc      | Commands to create, list and manage chat rooms
output   | Configure admin console output
port     | Commands to manage ports the server is listening on
pubsub   | Manage publish/subscribe nodes
role     | Role and access management
roster   | View and manage user rosters (contact lists)
s2s      | Commands to manage sessions between this server and others
server   | Uptime, version, shutting down, etc.
stats    | Commands to show internal statistics
user     | Commands to create and delete users, and change their passwords
watch    | Commands for watching live logs from the server
xmpp     | Commands for sending XMPP stanzas

各分区详解见第六章;migrate 分区在数据迁移场景使用(本文环境未涉及),output 分区控制台输出格式调整(帮助内容为空)。

三、前置条件

  • 已按部署篇完成 Prosody 13.0.7 安装、证书归位并以 systemd 托管(服务 active);
  • 已创建至少一个管理员账号(本文用 admin@xmpp.example.com);
  • 控制台命令(prosodyctl shell)要求配置中启用 admin_shell 模块(默认配置已含);
  • 全文示例域名与账号均为本文实验环境的真实取值,套用时替换为读者自己的域名/JID。

四、服务状态与信息类命令

4.1 prosodyctl status:运行状态

日常巡检第一条命令,确认服务进程与 PID:

prosodyctl status

实测回显(服务正常时):

Prosody is running with PID 5663

服务停止时实测:

Prosody is not running

服务因配置错误启动失败时,status 会提示读取系统日志(并给出 systemctl status prosody 建议),此时结合 journalctl -u prosody --no-pager | tail -20 定位。

4.2 prosodyctl version:版本号

prosodyctl version

实测回显:

Prosody 13.0.7

加 -v 输出运行环境全量明细(目录、Lua 环境、依赖库版本),排障时非常有用:

prosodyctl version -v

实测回显(全量):

Prosody 13.0.7

# Prosody directories
Data directory:     /var/lib/prosody
Config directory:   /etc/prosody
Source directory:   /usr/lib/prosody
Plugin directories:
  /var/lib/prosody/custom_plugins - not a directory!
  /usr/lib/prosody/modules/


# Operating system
Linux 6.8.0-138-generic

# Lua environment
Lua version:                    Lua 5.4

Lua module search paths:
  /usr/lib/prosody/prosody/?.lua
  /usr/lib/prosody/?.lua
  /usr/local/share/lua/5.4/prosody/?.lua
  /usr/local/share/lua/5.4/?.lua
  /usr/local/share/lua/5.4/prosody/?/init.lua
  /usr/local/share/lua/5.4/?/init.lua
  /usr/local/lib/lua/5.4/prosody/?.lua
  /usr/local/lib/lua/5.4/prosody/?/init.lua
  /usr/share/lua/5.4/prosody/?.lua
  /usr/share/lua/5.4/prosody/?/init.lua
  /usr/share/lua/5.4/?.lua
  /root/.luarocks/share/lua/5.4/?.lua
  /root/.luarocks/share/lua/5.4/?/init.lua
  /var/lib/prosody/custom_plugins/share/lua/5.4/?.lua
  /var/lib/prosody/custom_plugins/share/lua/5.4/?/init.lua

Lua C module search paths:
  /usr/lib/prosody/prosody/?.so
  /usr/lib/prosody/?.so
  /usr/local/lib/lua/5.4/prosody/?.so
  /usr/lib/x86_64-linux-gnu/lua/5.4/prosody/?.so
  /usr/lib/x86_64-linux-gnu/lua/5.4/?.so
  /usr/lib/lua/5.4/prosody/?.so
  /usr/lib/lua/5.4/?.so
  /usr/local/lib/lua/5.4/loadall.so
  /root/.luarocks/lib/lua/5.4/?.so
  /var/lib/prosody/custom_plugins/lib/lua/5.4/?.so

LuaRocks:               Installed (2.x+)

# Network

Backend: epoll

# Lua module versions
LuaDBI:         0.7
LuaExpat:       1.3.0
LuaFileSystem:  1.8.0
LuaSec:         1.0.2
LuaSocket:      3.0-rc1
luaunbound:     1.0.0
readline:       2.9

# library versions
libcrypto:      OpenSSL 3.0.2 15 Mar 2022
libunbound:     1.13.1

要点:Lua version: Lua 5.4 一行可验证部署篇修正解释器的成果;LuaDBI/LuaSec 等依赖版本是 SQL 存储与 TLS 问题排查的依据(详见《Prosody IM 13.0.7 配置参数详解》5.5 节的 LuaDBI 排障实录)。

4.3 prosodyctl about:安装信息

about 输出与 version -v 相同的全量环境信息(目录/Lua/网络后端/依赖版本),可任选其一。实测(节选,与 4.2 输出一致):

prosodyctl about | head -8
Prosody 13.0.7

# Prosody directories
Data directory:     /var/lib/prosody
Config directory:   /etc/prosody
Source directory:   /usr/lib/prosody
Plugin directories:
  /var/lib/prosody/custom_plugins - not a directory!
  /usr/lib/prosody/modules/

4.4 prosodyctl check:安装体检

对配置、DNS、证书做全面自检,改配置后、加域名后、证书更换后都应执行一遍:

prosodyctl check

实测回显(全量,本文环境含实验域名的 DNS 警告属预期——实验环境无公网 DNS 记录):

Checking config...

    Suggestion: If xmpp.example.com is a new host with no real users yet, consider renaming it now to
     example.com. You can use SRV records to redirect XMPP clients and servers to xmpp.example.com.
     For more information see: https://prosody.im/doc/dns

    Some of your hosts may be missing features due to a lack of configuration.
    For more details, use the 'prosodyctl check features' command.
Done.

Checking DNS for component chat.example.com...
    Host chat.example.com does not seem to resolve to this server (IPv4/IPv6)

Checking DNS for host xmpp.example.com...
    HTTP service xmpp.example.com has no A/AAAA record. Create one or change 'http_host' to the correct host.
    Host xmpp.example.com does not seem to resolve to this server (IPv4/IPv6)

Checking certificates...
Checking certificate for chat.example.com
  No 'certificate' found for chat.example.com
Checking certificate for xmpp.example.com
  Certificate: /etc/prosody/certs/xmpp.example.com.crt

For more information about certificates please see https://prosody.im/doc/certificates

Problems found, see above.

逐段解读:Checking config 段含 Lua 语法与配置合法性检查(语法错误会在这一步精确报行号,实测案例见《Prosody IM 13.0.7 配置参数详解》FAQ-1);Checking DNS 段验证各域名能否解析到本机,生产环境应全部通过(实验域名无 DNS 记录故报警);Checking certificates 段确认每个主机都有证书,chat.example.com 的警告在第七章 cert import 实测后可消除。

check 有子命令,最常用的是功能完整度报告:

prosodyctl check features

实测回显(全量):

Feature report
xmpp.example.com
        OK      Basic functionality
                Support for secure connections, authentication and messaging


        OK      Mobile optimizations
                Help mobile clients reduce battery and data usage


        OK      User profiles
                Enable users to publish profile information


        OK      Blocking
                Block communication with chosen entities


        OK      Push notifications
                Receive notifications on platforms that don't support persistent connections


        (!)     Multi-device messaging and data synchronization
                Multiple clients connected to the same account stay in sync

                Suggested modules:
                  - mam: https://prosody.im/doc/modules/mod_mam

        (!)     Web connections
                Allow connections from browser-based web clients

                Suggested modules:
                  - websocket: https://prosody.im/doc/modules/mod_websocket

        (!)     Audio/video calls and P2P
                Assist clients in setting up connections between each other

                Suggested modules:
                  - turn_external: https://prosody.im/doc/modules/mod_turn_external

        (!)     File sharing
                Sharing of files to groups and offline users

                Suggested component:

                        -- Documentation: https://prosody.im/doc/modules/mod_http_file_share
                        Component "share.xmpp.example.com" "http_file_share"

                If you have already configured any of these components, they may not be
                linked correctly to xmpp.example.com. For more info see https://prosody.im/doc/components

        (!)     Group chats
                Create group chats and channels

                Component "chat.example.com" is missing the following modules: mam

                Add the missing modules to your modules_enabled under the Component, like this:


                        -- Documentation: https://prosody.im/doc/modules/mod_muc
                        Component "chat.example.com" "muc"
                            modules_enabled = {
                                ...
                                "mam"; -- Add this!
                            }

要点:OK 项是当前配置已具备的能力;(!) 项给出缺失功能与可直接照抄的补齐建议(模块名/组件配置),是扩展功能时的最佳路线图。建议中的配置块中间部分本文以 ... 略去(完整建议在真实输出中为默认模块全集,照抄时以实际回显为准)。

4.5 prosodyctl reload:配置重载

prosodyctl reload

实测回显:

OK: Config reloaded (you may need to reload modules to take effect)

reload 等价于向服务进程发送 SIGHUP(日志可见 startup info Received SIGHUP):热载配置与重开日志文件,不换 PID、不断连接。注意与 systemctl reload prosody 效果相同,二选一即可;模块增删、VirtualHost 变更等结构性修改 reload 无效,必须 systemctl restart prosody(实测对照见《Prosody IM 13.0.7 配置参数详解》3.2 节)。

五、用户管理命令

5.1 prosodyctl adduser:交互式创建账号

adduser 以「JID」为参数,交互式询问两遍密码:

prosodyctl adduser lihua@xmpp.example.com

实测回显(密码经管道输入,交互终端下为隐藏输入):

Enter new password:
Retype new password:
OK: Created lihua@xmpp.example.com with role 'prosody:member'
exit=0

要点:账号默认授予 prosody:member 角色(普通成员);JID 必须写成「用户名@域名」全称,且域名必须是配置中已声明的 VirtualHost。重复创建同名账号的实测:

Error: User exists
exit=1

5.2 prosodyctl passwd / deluser:改密与删除

改密码(同样交互式两遍密码):

prosodyctl passwd lihua@xmpp.example.com

实测回显:

Enter new password:
Retype new password:
OK: User password changed
exit=0

对不存在的账号执行 passwd:

Error: No such user
exit=1

删除账号:

prosodyctl deluser wangwei@xmpp.example.com

实测回显:

OK: User deleted
exit=0

重复删除:

Error: No such user
exit=1

5.3 register:旧式一次性创建(含密码参数)

adduser 的交互形态不便脚本化,13.0 仍保留旧式 register 写法:prosodyctl register <用户名> <域名> <密码>,密码直接作参数:

prosodyctl register wangwei xmpp.example.com q1w2e3r4

实测回显:

usermanager         info        User account created: wangwei@xmpp.example.com
exit=0

⚠️ 注意:register 形态会把密码留在 shell 历史里,交互终端建议用 adduser;脚本化批量开户时注意清理历史或使用 HISTCONTROL。

5.4 数据落盘形态

账号创建后以「URL 编码域名」目录存储,验证:

find /var/lib/prosody -path "*accounts*" -name "*.dat"

实测回显:

/var/lib/prosody/xmpp%2eexample%2ecom/accounts/lihua.dat
/var/lib/prosody/xmpp%2eexample%2ecom/accounts/admin.dat
/var/lib/prosody/xmpp%2eexample%2ecom/accounts/wangwei.dat

域名中的 . 被编码为 %2e,每个账号一个 .dat 文件(默认 internal 存储,SCRAM 哈希格式);切换 SQL 后端后的落库形态见《Prosody IM 13.0.7 配置参数详解》5.5 节。

六、管理控制台 shell 详解

6.1 两种用法

prosodyctl shell 有两种用法。交互式:直接执行 prosodyctl shell 进入控制台(横幅如下,Ctrl+D 退出):

                     ____                \   /     _
                    |  _ \ _ __ ___  ___  _-_   __| |_   _
                    | |_) | '__/ _ \/ __|/ _ \ / _` | | | |
                    |_|   |_|  \___/|___/\___/ \__,_|\__, |
                    A study in simplicity            |___/


Welcome to the Prosody administration console. For a list of commands, type: help
You may find more help on using this console in our online documentation at
https://prosody.im/doc/console

一次执行式:把命令作为参数直接跟在 shell 后(本文全部采用此形态,便于脚本化):

prosodyctl shell <分区> <命令> [参数...]

💡 说明:控制台命令分区在前、子命令在后(如 user list、c2s show),与 --help 里的 c2s:show 冒号写法含义相同;一次执行形态统一用空格分隔。每个分区可用 prosodyctl shell help <分区> 查看该分区全部命令与参数说明。

6.2 user 分区:账号管理

user 分区是第五章 CLI 用户命令的增强版,全部命令支持非交互参数化。逐条实测:

prosodyctl shell user list xmpp.example.com
lihua@xmpp.example.com
admin@xmpp.example.com
OK: Showing all 2 users

支持模式过滤(第二参数):

prosodyctl shell user list xmpp.example.com zh
zhangsan@xmpp.example.com
OK: Showing 1 of 3 users

创建账号(第三个参数为角色,可省略默认 prosody:member):

prosodyctl shell user create zhangsan@xmpp.example.com q1w2e3r4 prosody:member
OK: Created zhangsan@xmpp.example.com with role 'prosody:member'

查看账号角色:

prosodyctl shell user role admin@xmpp.example.com xmpp.example.com
OK: prosody:operator

查看账号最后活跃时间:

prosodyctl shell user activity lihua@xmpp.example.com
OK: No activity

禁用/启用账号(禁用后拒绝登录、不删数据):

prosodyctl shell user disable zhangsan@xmpp.example.com
prosodyctl shell user enable zhangsan@xmpp.example.com
OK: User disabled
OK: User enabled

改密码与删除(与第五章 CLI 等效,但完全非交互):

prosodyctl shell user password zhangsan@xmpp.example.com q1w2e3r4
prosodyctl shell user delete zhangsan@xmpp.example.com
OK: User password changed
OK: User deleted

排查长期不上线的账号(时长支持 30d/12h 等后缀):

prosodyctl shell user list_inactive xmpp.example.com 30d
OK: 0 accounts inactive since 2026-09-21T11:17:32

💡 技术拓展:Prosody 的账号角色体系——user create 的角色参数与 user role 的输出对应以下内置角色(prosodyctl shell role list xmpp.example.com 实测):

prosody:operator
prosody:admin
prosody:member
prosody:registered
prosody:guest
OK: Showing 5 roles on xmpp.example.com
角色权限边界典型用途
prosody:operator服务器级全权(本文 admin 账号即此角色)服务管理员
prosody:admin域级管理(ad-hoc、广播等)域管理员
prosody:member普通注册用户(adduser 默认)内部成员
prosody:registered自助注册的受限用户开放注册服务器
prosody:guest最小权限访客访客账号

本文实际使用默认 prosody:member(普通账号)与 prosody:operator(管理账号)两档。

6.3 host 分区:虚拟主机

prosodyctl shell host list
chat.example.com (muc component)
xmpp.example.com
OK: 2 hosts

运行时激活一个新域名(无需改配置文件与重启,立即生效):

prosodyctl shell host activate lab.example.net
prosodyctl shell host list
Result: true
chat.example.com (muc component)
xmpp.example.com
lab.example.net
OK: 3 hosts

停用(会断开该域名上的全部客户端):

prosodyctl shell host deactivate lab.example.net
prosodyctl shell host list
Result: true
chat.example.com (muc component)
xmpp.example.com
OK: 2 hosts

⚠️ 注意:host activate 是运行时激活,不写入配置文件——服务重启后消失。要永久启用域名仍需在配置中添加 VirtualHost 段。

6.4 module 分区:模块热管理

列出某主机已加载的模块:

prosodyctl shell module list xmpp.example.com

实测回显(全量,45 项):

xmpp.example.com:
    account_activity
    adhoc
    admin_adhoc
    admin_shell
    auth_internal_hashed
    authz_internal
    blocklist
    bookmarks
    bosh
    c2s
    carbons
    cloud_notify
    cron
    csi
    csi_simple
    dialback
    disco
    http
    http_altconnect
    invites
    invites_adhoc
    invites_register
    iq
    limits
    message
    offline
    pep
    ping
    presence
    private
    register
    register_ibr
    register_limits
    roster
    s2s
    saslauth
    smacks
    storage_internal
    time
    tls
    tokenauth
    uptime
    user_account_management
    vcard4
    vcard_legacy
    version
Result: nil

MUC 组件主机的模块列表(Component "chat.example.com" "muc" 段):

chat.example.com:
    adhoc
    admin_shell
    authz_internal
    dialback
    disco
    iq
    muc
    muc_unique
    s2s
    saslauth
    smacks
    storage_internal
    tls
    vcard
Result: nil

查看单个模块详情:

prosodyctl shell module info tls xmpp.example.com
on VirtualHost "xmpp.example.com"
  path: /usr/lib/prosody/modules/mod_tls.lua
  status: [core] Loaded
Result: true

热加载模块(示例:加载 WebSocket 支持,无需重启):

prosodyctl shell module load websocket xmpp.example.com
Loaded for *
Note: Module will not be loaded after restart unless enabled in configuration
OK: Module loaded onto 1 host

卸载:

prosodyctl shell module unload websocket xmpp.example.com
Unloaded from *
Unloaded from xmpp.example.com
OK: Module unloaded from 2 hosts

加载不存在的模块实测:

prosodyctl shell module load nosuchmod xmpp.example.com
/usr/lib/prosody/modules/share/lua/5.4/mod_nosuchmod/mod_nosuchmod.lua: No such file or directory
Error: Last error: /usr/lib/prosody/modules/share/lua/5.4/mod_nosuchmod/mod_nosuchmod.lua: No such file or directory

⚠️ 注意 module load 的提示行:"Module will not be loaded after restart unless enabled in configuration"——热加载只对当前进程有效,永久启用必须在配置 modules_enabled 中添加并重启(详见《Prosody IM 13.0.7 配置参数详解》5.6 节)。

6.5 c2s 分区:客户端会话管理

c2s(client-to-server)分区管理本地客户端的在线会话。命令输出需要「有会话在线」才有内容,先准备一个在线客户端:任意 XMPP 客户端(Gajim、Pidgin 等)以 admin@xmpp.example.com 登录即可。无图形客户端时,可用以下最小 Python 脚本(标准库实现 STARTTLS + SASL PLAIN + bind,登录后保持在线 60 秒):

#!/usr/bin/env python3
# xmpp_hold.py —— 最小在线会话:登录后保持 60 秒,期间在另一终端执行 c2s show
import socket, ssl, base64, time
HOST, PORT, DOMAIN, USER, PASS = "127.0.0.1", 5222, "xmpp.example.com", "admin", "q1w2e3r4"
STREAM = ("<?xml version='1.0'?><stream:stream to='%s' xmlns='jabber:client' "
          "xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>" % DOMAIN)
def rx(s, tag):
    data = b""; s.settimeout(5)
    try:
        while True:
            chunk = s.recv(65536)
            if not chunk: break
            data += chunk
            if b"success" in data or b"failure" in data or b"result" in data or b"</stream:features>" in data:
                break
    except socket.timeout:
        pass
    print("[%s] %s" % (tag, data.decode(errors="replace")[:200]))
s = socket.create_connection((HOST, PORT), timeout=5)
s.sendall(STREAM.encode()); rx(s, "features")
s.sendall(b"<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); rx(s, "proceed")
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT); ctx.check_hostname = False; ctx.verify_mode = ssl.CERT_NONE
t = ctx.wrap_socket(s, server_hostname=DOMAIN)
print("[tls]", t.version(), t.cipher()[0])
t.sendall(STREAM.encode()); rx(t, "features2")
tok = base64.b64encode(("\0" + USER + "\0" + PASS).encode()).decode()
t.sendall(("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>%s</auth>" % tok).encode()); rx(t, "auth")
t.sendall(STREAM.encode()); rx(t, "features3")
t.sendall(("<iq type='set' id='b1'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>cli</resource></bind></iq>").encode()); rx(t, "bind")
print("[hold] 在线 60 秒"); time.sleep(60); t.close()

实测(另一终端登录会话在线后)会话数统计:

prosodyctl shell c2s count
OK: Total: 1 clients

列出全部会话:

prosodyctl shell c2s show
Session ID           | JID                                  | Role         | IPv  | Status  | Security  | SM          | CSI State
c2s60b9f00fc2a0      | admin@xmpp.example.com/cli-doc       | operator     | IPv4 |         | TLSv1.3   | no          |
OK: 1 c2s sessions shown

逐列解读:Session ID 为会话唯一标识(排障时与日志行 c2s60b9f00fc2a0 对应);JID 含客户端资源名;Security 列显示 TLS 版本;SM 列为流恢复(XEP-0198)协商状态;CSI State 为客户端节能状态。

查看会话加密细节:

prosodyctl shell c2s show_tls admin@xmpp.example.com
JID                                                             | Session ID           | Security  | Encryption
admin@xmpp.example.com/cli-doc                                  | c2s60b9f00fc2a0      | TLSv1.3   | TLS_AES_256_GCM_SHA384
OK: 1 c2s sessions shown

强制断开指定用户的全部会话(踢线):

prosodyctl shell c2s close admin@xmpp.example.com
OK: Total: 1 sessions closed

断开后稍候复查确认:

prosodyctl shell c2s show
Session ID           | JID                                  | Role         | IPv  | Status  | Security  | SM          | CSI State
OK: 0 c2s sessions shown

服务端踢线的客户端侧感知(Python 脚本日志实测):连接收到 TLS EOF(ssl.SSLZeroReturnError: TLS/SSL connection has been closed (EOF)),即服务端优雅关闭流。

c2s closeall 关闭服务器上全部客户端会话(维护窗口前使用)。

6.6 s2s 分区:服务器互联会话

s2s(server-to-server)分区管理与其他 XMPP 服务器的联邦会话。无联邦对端时:

prosodyctl shell s2s show
Session ID           | Host                     | Dir  | Remote                   | IPv  | Security  | SASL       | Dialback
OK: 0 s2s connections shown

实测与公网 XMPP 服务器 jabber.org 建立出站联邦连接(向对端域用户发送 ping 触发 s2s 拨号):

prosodyctl shell xmpp ping admin@xmpp.example.com demo@jabber.org
Session s2sout58c709aa71f0 (xmpp.example.com-->jabber.org) connected (1.6065s)

连接建立后查看 s2s 会话状态:

prosodyctl shell s2s show
Session ID           | Host                     | Dir  | Remote                   | IPv  | Security  | SASL       | Dialback
s2sout58c709aa71f0   | xmpp.example.com         | -->  | jabber.org               | IPv4 | TLSv1.3   |            | Initiated
OK: 1 s2s connections shown

要点:Dir 列 --> 表示出站连接;Security 列显示 TLSv1.3 加密;Dialback 列 Initiated 表示域名所有权回拨验证进行中(对端验证通过后进入正常消息交换)。关闭全部联邦连接:

prosodyctl shell s2s closeall xmpp.example.com
OK: Closed 1 s2s session

s2s close <from> <to> 可精确断开某一对域名间的连接;s2s show_tls <域名> 查看联邦连接加密细节。

6.7 muc 分区:聊天室管理

列出 MUC 组件上的房间(初始为空):

prosodyctl shell muc list chat.example.com
OK: 0 rooms

创建房间(房间 JID = 房间名@组件域名):

prosodyctl shell muc create dev-room@chat.example.com
prosodyctl shell muc create meeting-room@chat.example.com
Result: MUC room (dev-room@chat.example.com)
Result: MUC room (meeting-room@chat.example.com)

再次列出:

prosodyctl shell muc list chat.example.com
meeting-room@chat.example.com
dev-room@chat.example.com
OK: 2 rooms

查看房间成员与身份列表(空房间):

prosodyctl shell muc occupants dev-room@chat.example.com
prosodyctl shell muc affiliations dev-room@chat.example.com
OK: 0 out of 0 occupants listed
OK: 0 out of 0 affiliationss listed

(affiliationss 三连 s 为 13.0.7 输出原样。)

⚠️ 注意:help muc 列出的命令只有 affiliations/create/list/occupants/room 五个,没有房间销毁命令——实测执行不存在的 muc destroy 会得到:

Error: Command not found or necessary module not loaded. Try 'help muc for a list of available commands.

而 muc room <房间JID> 只返回房间对象引用,不能链式销毁(实测 prosodyctl shell muc room meeting-room@chat.example.com destroy 仅输出 Result: MUC room <meeting-room@chat.example.com>,房间仍在)。删除房间需在 XMPP 客户端内由房间所有者执行销毁操作。

6.8 config 分区:运行时配置查看与修改

config get 查看运行中的配置值(* 表示全局段):

prosodyctl shell config get "*" limits
prosodyctl shell config get xmpp.example.com authentication
OK: {
        c2s = {
                rate = "10kb/s";
        };
        s2sin = {
                rate = "30kb/s";
        };
}
OK: "internal_hashed"

config set 运行时修改(不写入配置文件):

prosodyctl shell config set "*" archive_expires_after 2w
prosodyctl shell config get "*" archive_expires_after
Result: true
OK: "2w"

执行 config reload 后运行时值回落为配置文件中的值(实测闭环):

prosodyctl shell config reload
prosodyctl shell config get "*" archive_expires_after
OK: Config reloaded (you may need to reload modules to take effect)
OK: "1w"

⚠️ 注意三点:config set 是纯运行时修改,重启后失效,要持久化必须改配置文件;config reload 等价 prosodyctl reload,且如提示所说明——配置重载后部分模块需要单独 reload 才感知新值。

6.9 dns 分区:内部解析器

prosodyctl shell dns lookup xmpp.example.com A
prosodyctl shell dns cache
OK: Status: No Error
OK: Cache:
nil

dns lookup <名称> <类型> 用 Prosody 内置解析器(luaunbound)做 DNS 查询,诊断联邦失败(对端 SRV/A 记录缺失)时使用;dns cache/dns purge 查看与清空解析缓存;dns addnameserver/dns setnameserver 调整解析器使用的上游。

6.10 roster 分区:花名册(联系人列表)

管理员可直接读写用户的花名册,实测让两个账号互为联系人:

prosodyctl shell roster subscribe lihua@xmpp.example.com admin@xmpp.example.com
prosodyctl shell roster subscribe admin@xmpp.example.com lihua@xmpp.example.com
prosodyctl shell roster show lihua@xmpp.example.com
Result: true
Result: true
admin@xmpp.example.com  sub=both        ask=none
OK: Showing 1 entries

sub=both 表示双方互已订阅。其余命令:roster subscribe_both 一步建立双向订阅、roster unsubscribe/unsubscribe_both 取消订阅、roster clean 清理失效联系人。

6.11 server / port / http / cron 分区

服务运行信息:

prosodyctl shell server uptime
prosodyctl shell server version
prosodyctl shell server memory
OK: This server has been running for 0 days, 1 hour and 4 minutes (since Wed Oct 21 10:13:42 2026)
OK: 13.0.7
Process: 7.52 MiB
   Used: 7.16 MiB (4.3 MiB by Lua)
   Free: 110 KiB (79.3 KiB returnable)
OK: OK

监听端口总览:

prosodyctl shell port list
c2s: [*]:5222, [::]:5222
http: [127.0.0.1]:5280, [::1]:5280
https: [*]:5281, [::]:5281
s2s: [*]:5269, [::]:5269
OK: 4 services listening on 8 ports

HTTP 端点清单(启用 http/bosh 后):

prosodyctl shell http list
Global HTTP endpoints available on all hosts:
Module            | External URL                                          | Internal URL
mod_bosh           | https://*:5281/http-bind

HTTP endpoints on xmpp.example.com:
Module            | External URL                                          | Internal URL
mod_bosh           | https://xmpp.example.com:5281/http-bind
mod_http_altconne… | https://xmpp.example.com:5281/.well-known

HTTP requests to unknown hosts will return 404 Not Found
Result: true

周期任务(mod_cron 注册的内部定时任务):

prosodyctl shell cron tasks
Host                  | Task                             | Desc                             | When       | Last run
xmpp.example.com      | tokenauth/clear_expired_grants   | clear expired grants             | daily      | 2026-10-21 09:44:54
xmpp.example.com      | user_account_management/remove_… | Remove deleted accounts          | daily      | 2026-10-21 09:44:54
Result: nil

server shutdown <原因> 可从控制台关停服务(原因会广播给在线客户端),日常启停仍建议用 systemd。

6.12 stats 分区:内置统计

stats show 需要先在配置全局段启用统计,否则实测报错:

prosodyctl shell stats show
Error: Statistics disabled. Try `statistics = "internal"` in the global section of the config file and restart.

按提示在 /etc/prosody/prosody.cfg.lua 全局段加入 statistics = "internal" 并 systemctl restart prosody 后重测:

prosodyctl shell stats show

实测回显(节选,全量约百行):

prosody_dns_seconds
prosody_info
  version=13.0.7                                   1
prosody_mod_bosh/active_sessions                   0
prosody_mod_bosh/bad_host                          0 events/s [avg]
prosody_mod_bosh/bad_sid                           0 events/s [avg]
prosody_mod_bosh/inactive_sessions                 0
prosody_mod_bosh/new_sid                           0 events/s [avg]
prosody_mod_bosh/timeout                           0 events/s [avg]
prosody_mod_c2s/connections
prosody_mod_c2s/encrypted
prosody_mod_csi/changes_events
prosody_mod_csi/state_sessions
  host=xmpp.example.com csi_state=flushing         0 sessions
  host=xmpp.example.com csi_state=active           0 sessions
  host=xmpp.example.com csi_state=inactive         0 sessions
prosody_mod_csi_simple/buffer_hold_seconds
  host=xmpp.example.com                            no obs.
prosody_mod_csi_simple/flush_stanza_count
  host=xmpp.example.com                            no obs.
prosody_mod_csi_simple/flushes
prosody_mod_muc/live_room
  host=chat.example.com                            0
prosody_mod_muc/room_eviction
  host=chat.example.com                            0 events/s [avg]
prosody_mod_muc/room_hit
  host=chat.example.com                            0 events/s [avg]
prosody_mod_muc/room_miss
  host=chat.example.com                            0 events/s [avg]
prosody_mod_s2s/accepted_tcp                       0 events/s [avg]

支持按名称过滤:

prosodyctl shell stats show c2s
prosody_mod_c2s/connections
prosody_mod_c2s/encrypted
Result: 2 statistics displayed

统计开启方式与监控对接(statistics_config、OpenMetrics 端点)属调优范畴,配置细节见《Prosody IM 13.0.7 配置参数详解》。

6.13 role / limits / debug / xmpp 分区

角色清单(角色体系见 6.2 拓展说明):

prosodyctl shell role list xmpp.example.com
prosody:operator
prosody:admin
prosody:member
prosody:registered
prosody:guest
OK: Showing 5 roles on xmpp.example.com

role show <host> <role_name> 查看角色包含的权限项;user set_role <jid> <host> <role> 为账号改角色。

每 IP 连接限制状态(未配置限制时):

prosodyctl shell limits connections 127.0.0.1
Error: No per-IP limits are configured

调试分区示例——查看已注册的定时器:

prosodyctl shell debug timers

实测回显(节选前 6 行):

-- net.server.timer
2026-10-21 11:19:14     function @unbound.lua:154()
2026-10-21 11:21:56     function @server_epoll.lua:406()
2026-10-21 11:32:56     function @server_epoll.lua:380()
2026-10-21 12:13:43     function @mod_cron.lua:62()
OK: Next event at 2026-10-21 11:19:14 (in 18.180548s)

debug 分区其余命令:debug async(挂起的异步任务)、debug events <host> <event>(事件处理器注册表)、debug logevents(实时打印事件触发)、debug cert_index <路径>(证书目录索引视图)。watch log 实时跟踪日志流、watch stanzas <目标> 实时监视符合条件的 XML 段——深度排障时使用。

向 XMPP 实体发 ping 并测时延(本地服务器实体):

prosodyctl shell xmpp ping admin@xmpp.example.com xmpp.example.com
OK: pong from xmpp.example.com in 4.91142e-05s

6.14 invite / pubsub / migrate 分区边界

help 列出的三个分区在 13.0.7 默认安装下执行报 Command not found,属「帮助已列出、命令实现未随包提供」的版本边界(排障见 FAQ-6):

prosodyctl shell invite list xmpp.example.com
Error: Command not found. Is the necessary module loaded?
prosodyctl shell pubsub list_nodes pubsub.xmpp.example.com
Error: Command not found. Is the necessary module loaded?

说明:invite 分区命令的提供模块未包含在官方包内(配置中已加载 invites/invites_adhoc/invites_register 三模块仍报错,实测确认);pubsub 分区需先在配置中声明 Component "pubsub.xmpp.example.com" "pubsub" 组件并加载后才可用。migrate 分区用于 internal↔SQL 存储迁移,本文环境未配置 SQL 后端,无实际迁移对象。

七、证书管理命令 cert

7.1 子命令总览

prosodyctl cert --help

实测回显(全量):

Usage: /usr/bin/prosodyctl cert config|request|generate|key|import
 Helpers for generating X.509 certificates and keys.

Usage: /usr/bin/prosodyctl cert generate HOSTNAME [HOSTNAME+]
 Generates a self-signed certificate for the current hostname(s)

Usage: /usr/bin/prosodyctl cert config HOSTNAME [HOSTNAME+]
 Builds a certificate config file covering the supplied hostname(s)

Usage: /usr/bin/prosodyctl cert request HOSTNAME [HOSTNAME+]
 Generates a certificate request for the supplied hostname(s)

Usage: /usr/bin/prosodyctl cert import [HOSTNAME+] /path/to/certs [/other/paths/]+
 Copies certificates to /var/lib/prosody

Usage: /usr/bin/prosodyctl cert key HOSTNAME <bits>
 Generates a RSA key named HOSTNAME.key
 Prompts for a key size if none given

💡 技术拓展:XMPP 服务器证书的常见来源对比——

来源原理适用场景
自签(cert generate)自己当 CA 签发,客户端需手动信任内网、测试环境
Let's Encrypt(certbot + cert import)ACME 自动签发受信证书,90 天轮换有公网域名的生产环境
商业 CA购买年付证书无法自动化 ACME 的环境

本文实验采用自签(部署篇)演示 cert generate,并用自签证书模拟外部签发目录演示 cert import。

⚠️ 前置条件:cert 全部子命令要求目标主机名已写在配置文件的 VirtualHost/Component 段中,否则一律拒绝(实测见 FAQ-2)。

7.2 cert generate:自签证书

prosodyctl cert generate lab.example.net

实测回显(交互输入直接回车取默认值):

Choose key size (2048): Key written to /var/lib/prosody/lab.example.net.key
Please provide details to include in the certificate config file.
Leave the field empty to use the default value or '.' to exclude the field.
countryName (GB): localityName (The Internet): organizationName (Your Organisation): organizationalUnitName (XMPP Department): commonName (lab.example.net): emailAddress (xmpp@lab.example.net):
Config written to /var/lib/prosody/lab.example.net.cnf
Certificate written to /var/lib/prosody/lab.example.net.crt

exit=0

要点:密钥位数交互询问(默认 2048);证书字段全部有默认值(国家 GB、组织 Your Organisation 等,直接回车即用);产物落在数据目录 /var/lib/prosody/(<域名>.key/.cnf/.crt 三件),而非 /etc/prosody/certs/——certmanager 对两个位置都会索引(/etc/prosody/certs/ 优先),自签证书落数据目录即可被服务加载。

7.3 cert key / config / request

生成指定长度的 RSA 密钥:

prosodyctl cert key lab.example.net 2048
Key written to /var/lib/prosody/lab.example.net.key
exit=0

生成本次 let's encrypt 申请要用的证书配置文件(CSR 申请前的字段问卷,交互式):

prosodyctl cert config lab.example.net

实测回显:

Please provide details to include in the certificate config file.
Leave the field empty to use the default value or '.' to exclude the field.
countryName (GB): localityName (The Internet): organizationName (Your Organisation): organizationalUnitName (XMPP Department): commonName (lab.example.net): emailAddress (xmpp@lab.example.net):
Config written to /var/lib/prosody/lab.example.net.cnf
exit=0

cert request lab.example.net 生成 CSR(证书签发请求,交 CA 签名用)。三者都属于向外部 CA 申请证书的准备步骤;自签场景用 cert generate 一步到位即可。

⚠️ 注意:这三个子命令在目标文件已存在时会交互确认 ... exists, do you want to replace it? [y/n]——在无终端的脚本/管道环境执行时,该交互会直接抛出 Lua 错误(实测回显见 FAQ-3)。脚本化使用前先清理旧产物或更换主机名。

7.4 cert import:外部证书归位

cert import 把外部签发的证书拷贝进 /var/lib/prosody/,解决「Let's Encrypt 续期后证书不在 Prosody 目录」的问题。实测:

准备外部证书目录(模拟 certbot 的 live 目录;文件名必须为 <域名>.crt + <域名>.key):

mkdir -p /srv/ext-certs
cp /etc/letsencrypt/live/xmpp.example.com/fullchain.pem /srv/ext-certs/xmpp.example.com.crt   # 示意;本文用自签模拟
openssl req -x509 -newkey rsa:2048 -keyout /srv/ext-certs/lab.example.net.key -out /srv/ext-certs/lab.example.net.crt -days 30 -nodes -subj "/CN=lab.example.net"
chmod 755 /srv/ext-certs && chmod 644 /srv/ext-certs/*

导入:

prosodyctl cert import lab.example.net /srv/ext-certs

实测回显:

Imported certificate and key for hosts lab.example.net
exit=0

验证落位与热加载(导入动作会自动触发 SIGHUP 重载证书):

ls -la /var/lib/prosody/ | grep -i lab
-rw-r----- 1 prosody prosody  1131 Oct 21 11:23 lab.example.net.crt
-r-------- 1 prosody prosody  1704 Oct 21 11:23 lab.example.net.key
tail -3 /var/log/prosody/prosody.log
Oct 21 11:23:54 startup info    Received SIGHUP
Oct 21 11:23:54 startup info    Reloading configuration file
Oct 21 11:23:54 chat.example.com:tls    info    Certificates reloaded

cert import 可一次传多个目录(cert import <域名> <目录1> <目录2>...),也可省略域名让它扫描全部传入目录并把能匹配配置内主机名的证书全部归位。排障实录(目录权限、文件命名)见 FAQ-4。

八、社区插件管理

8.1 plugin_server:安装前置

prosodyctl install 从 Prosody 社区模块仓库(rocks 格式)安装第三方模块。13.0.7 下未配置 plugin_server 时直接报错:

prosodyctl install mod_privilege
There is no 'plugin_server' option in the configuration file
exit=1

在 /etc/prosody/prosody.cfg.lua 全局段添加官方模块仓库地址后重试:

plugin_server = "https://modules.prosody.im/rocks"

8.2 install / list / remove 实测

安装社区模块 mod_privilege(特权实体,XEP-0356):

prosodyctl install mod_privilege

实测回显(全量):

Installing mod_privilege in /var/lib/prosody/custom_plugins
Installing https://modules.prosody.im/rocks/mod_privilege-28-1.src.rock

No existing manifest. Attempting to rebuild...
mod_privilege 28-1 is now installed in /var/lib/prosody/custom_plugins (license: MIT)

Done.
If you installed a prosody plugin, don't forget to add its name under the 'modules_enabled' section inside your configuration file.
Depending on the module, there might be further configuration steps required.

More info about:
        modules_enabled: https://prosody.im/doc/modules_enabled
        mod_privilege: https://modules.prosody.im/mod_privilege.html
exit=0

列出已安装插件:

prosodyctl list

Rocks installed for Lua 5.4 in /var/lib/prosody/custom_plugins
--------------------------------------------------------------

mod_privilege
   28-1 (installed) - /var/lib/prosody/custom_plugins/lib/luarocks/rocks-5.4

安装后即可热加载(等价内置模块的 module load):

prosodyctl shell module load privilege xmpp.example.com
Loaded for xmpp.example.com
Note: Module will not be loaded after restart unless enabled in configuration
OK: Module loaded onto 1 host

确认已出现在模块列表(节选):

prosodyctl shell module list xmpp.example.com | grep -A1 privilege
    privilege
    register

卸载:

prosodyctl remove mod_privilege

实测回显:

Removing mod_privilege from /var/lib/prosody/custom_plugins
Checking stability of dependencies in the absence of
mod_privilege 28-1...

Removing mod_privilege 28-1...
Removal successful.
exit=0

要点:插件落盘 /var/lib/prosody/custom_plugins/(luarocks 目录结构),该目录已在默认插件搜索路径中(prosodyctl about 的 Plugin directories 一节可见);remove 会做依赖稳定性检查。注意 install/remove 的参数带 mod_ 前缀(如 mod_privilege),而 module load 的参数不带前缀(如 privilege)。

九、注意事项

  1. prosodyctl 与 systemctl 分工:服务启停/自启走 systemctl;账号/证书/插件/诊断走 prosodyctl。prosodyctl reload 与 systemctl reload prosody 同效,勿叠加。
  2. 一次性执行优于交互:prosodyctl shell <命令> 的形态可进脚本、可记录;交互控制台适合探索。
  3. 运行时修改不持久:config set、module load、host activate 都是进程内存态,重启即失;持久化一律回到配置文件。
  4. JID 全称:用户管理命令一律用「用户名@域名」全称;register 旧式命令才拆「用户名 域名」两个参数。
  5. 无终端交互命令脚本化要谨慎:adduser/passwd/cert 系列在无 TTY 环境可能因密码输入或 y/n 确认失败,脚本场景改用 shell user create/password(参数化)或提前清理旧产物。
  6. 以非 root 运行提示:prosodyctl 会对 root 执行打警告(Danger, Will Robinson!),属提醒不影响功能;服务进程本身以 prosody 用户运行。
  7. 配置检查习惯:任何配置修改后先 prosodyctl check 再重启,能在启动失败前发现语法与引用错误。

十、常见问题(FAQ)

FAQ-1:stats show 报 Statistics disabled

现象:prosodyctl shell stats show 报 Error: Statistics disabled. Try statistics = "internal" in the global section of the config file and restart.

定位与解决:内置统计默认关闭。在配置全局段加 statistics = "internal" 后 systemctl restart prosody,重测即出数据(完整实测见 6.12 节)。

FAQ-2:cert 子命令报 The given hostname does not exist in the config

现象:对配置中不存在的域名执行 cert generate/key/config/request/import,实测:

The given hostname does not exist in the config
exit=1

定位:cert 工具先校验主机名是否出现在配置文件(VirtualHost/Component 段)中,运行时 host activate 激活的域名不算(不写配置文件)。

解决:先把域名写进配置(VirtualHost "lab.example.net"),再执行 cert 子命令(实测通过见 7.2 节)。

FAQ-3:cert 交互确认在脚本环境抛 Lua 错误

现象:目标 key/证书文件已存在时,cert key/config/request 会问 ... exists, do you want to replace it? [y/n];在无终端的管道环境实测直接崩溃:

lua: /usr/bin/prosodyctl:631: /usr/share/lua/5.4/prosody/util/human/io.lua:18: attempt to index a nil value (local 'char')
stack traceback:
        /usr/share/lua/5.4/prosody/util/human/io.lua:18: in function 'prosody.util.human.io.getchar'
        /usr/share/lua/5.4/prosody/util/human/io.lua:52: in function 'prosody.util.human.io.show_yesno'
        ...
/var/lib/prosody/lab.example.net.key exists, do you want to replace it? [y/n] exit=1

定位:show_yesno 需要从 TTY 读单字符,管道环境下读到 EOF(nil)即抛错。

解决:脚本化场景先删除既有产物(rm /var/lib/prosody/<域名>.*)再执行;或改在交互终端操作。

FAQ-4:cert import 报 No certificate for host ... found :(

现象与定位(两个独立原因,均实测踩中):

  1. key 文件命名不符:导入目录里 key 命名为 <域名>.pem 时报 No certificate for host lab.example.net found :( / No certificates imported :(——import 按 <域名>.crt + <域名>.key 的固定命名匹配。解决:改名 mv lab.example.net.pem lab.example.net.key 后重试即成功。
  2. 源目录权限不足:目录放在 /root/ext-certs(700)时,报:
certmanager         error       Error indexing certificate directory /root/ext-certs: cannot open /root/ext-certs: Permission denied
No certificate for host chat.example.com found :(
No certificate for host xmpp.example.com found :(
No certificates imported :(
exit=1

解决:外部目录放常规路径(如 /srv/ext-certs)并保证 prosody 用户可读(目录 755、文件 644)。

FAQ-5:prosodyctl install 报 There is no 'plugin_server' option

现象与解决见 8.1 节:配置全局段补 plugin_server = "https://modules.prosody.im/rocks" 后安装正常。

FAQ-6:shell 命令报 Command not found. Is the necessary module loaded?

现象:help 分区里列出的命令执行报错,实测 invite 分区(模块 invites/invites_adhoc/invites_register 均已加载仍报错):

Error: Command not found. Is the necessary module loaded?

定位:prosodyctl shell help 的分区表是控制台命令总目录,不等于当前安装可用的命令集——部分分区命令的实现(如 invite 的控制台管理命令)未随 13.0.7 官方包提供。已用 grep -n invite /usr/lib/prosody/modules/mod_admin_shell.lua 实证:命令注册表中确无 invite 条目。

解决:邀请管理改走客户端内的 ad-hoc 命令(invites_adhoc 已加载,支持 ad-hoc 的客户端可用)或社区模块补充;pubsub 分区则需先声明 pubsub 组件。

FAQ-7:客户端发送 SMACKS <r/> 保活被断开

现象:以 Python 标准库自建 c2s 会话(已 bind),向服务器发送流管理保活标签 <r xmlns='urn:xmpp:sm:3'/>,连接随即被服务端关闭,客户端报 ssl.SSLZeroReturnError: TLS/SSL connection has been closed (EOF)。服务端日志(实测照抄):

stanzarouter    warn    Unhandled c2s stream element or stanza: r; xmlns=urn:xmpp:sm:3: <r xmlns='urn:xmpp:sm:3' xml:lang='en'/>
c2s60b9f072aa50 info    Client disconnected: connection closed

定位:SMACKS(XEP-0198)要求客户端先在流协商阶段发送 <enable xmlns='urn:xmpp:sm:3'/> 完成协商;未协商直接发 <r/> 属未处理元素,服务端 warn 后关闭流。

解决:保活改用标准 XMPP ping(<iq type='get'><ping xmlns='urn:xmpp:ping'/></iq>,实测会话稳定保持,见 6.5 节);或按 XEP-0198 先 <enable> 再使用 SM 机制。

FAQ-8:module load 的模块重启后失效

现象:prosodyctl shell module load <模块> 成功,服务重启后模块没了。

定位:module load 的输出已明示——Note: Module will not be loaded after restart unless enabled in configuration。运行时加载只存在于当前进程。

解决:在配置 modules_enabled 列表中加入模块名并 systemctl restart prosody(实测流程见《Prosody IM 13.0.7 配置参数详解》5.6 节)。

十一、参考链接