Ejabberd源码解析前奏--管理

时间:2022-08-30 09:07:04

一、ejabberdctl

使用ejabberdctl命令行管理脚本,你可以执行ejabberdctl命令和一些普通的ejabberd命令(后面会详细解说)。这意味着你可以在一个本地或远程ejabberd服务器(通过提供参数 --node NODENAME)上启动、停止以及执行很多其它管理任务。

ejabberdctl脚本可在文件 ejabberdctl.cfg 里配置. 这个文件包含每个可配置选项的详细信息.

ejabberdctl脚本返回一个数字状态码. 成功显示为0, 错误显示为1, 其它码可被用于特定结果. 这可以由其它脚本使用,来自动决定一个命令成功与否, 例如使用: echo $?。

1、ejabberdctl命令

不带任何参数执行ejabberdctl时, 它显示可用的选项. 如果没有一个ejabberd服务器在运行, 可用的参数如下:

    start

以后台模式启动ejabberd. 这是缺省方法.

    debug

连接一个 Erlang shell 到一个已存在的 ejabberd 服务器. 这允许在ejabberd服务器上执行交互命令.

    live

以live模式启动ejabberd: shell保持连接到已启动的服务器, 显示日志信息并允许执行交互命令.

如果已经有一个ejabberd服务器在系统里运行, ejabberdctl 展示以下 ejabberdctl 命令描述以及那台服务器上所有可用的 ejabberd命令.

ejabberdctl命令如下:

    help

获得关于ejabberdctl或任何可用命令的帮助. 试下ejabberdctl help help.

    status

检查ejabberd服务器的状态.

    stop

停止ejabberd服务器.

    restart

重启ejabberd服务器.

    mnesia

获得关于Mnesia数据库的信息.

ejabberdctl脚本可被限制为需要验证并执行一些ejabberd命令,增加这个选项到文件 ejabberd.cfg. 下面例子表示没有限制:

{ejabberdctl_access_commands, []}.

如果帐号robot1@example.org被注册到ejabberd,密码为abcdef(作MD5后为E8B501798950FC58AAD83C8C14978E), 并且 ejabberd.cfg 包含以下设定:

{hosts, ["example.org"]}.

{acl, bots, {user, "robot1", "example.org"}}.

{access, ctlaccess, [{allow, bots}]}.

{ejabberdctl_access_commands, [ {ctlaccess, [registered_users, register], []} ]}.

那么你可以在 shell 里这么做:

$ ejabberdctl registered_users example.org

Error: no_auth_provided

$ ejabberdctl --auth robot1 example.org E8B501798950FC58AAD83C8C14978E registered_users example.org

robot1

testuser1

testuser2

2、Erlang运行时系统

ejabberd是一个 Erlang/OTP 应用,运行在一个Erlang运行时系统内部. 这个系统是用环境变量和命令行参数来配置的. ejabberdctl管理脚本可能会使用其中的一些. 你可以在ejabberdctl.cfg文件里配置其中的一部分, 配置文件里面已包含了关于它们的详细描述. 本节描述所有环境变量和命令行参数的意义.

环境变量:

    EJABBERD_CONFIG_PATH

ejabberd配置文件的路径.

    EJABBERD_MSGS_PATH

翻译字符串的目录路径.

    EJABBERD_LOG_PATH

ejabberd服务日志文件的路径.

    EJABBERD_SO_PATH

二进制系统库的目录路径.

    EJABBERD_DOC_PATH

ejabberd文档的目录路径.

    EJABBERD_PID_PATH

ejabberd启动时建立PID文件的路径.

    HOME

ejabberd的Home目录的路径. 这个路径用于读取文件.erlang.cookie.

    ERL_CRASH_DUMP

崩溃报告dump文件的路径.

    ERL_INETRC

指示使用名字解析的IP. 如果使用 -sname, 要么指定这个选项,要么指定 -kernel inetrc filepath.

    ERL_MAX_PORTS

并发开放的Erlang端口的最大数量.

    ERL_MAX_ETS_TABLES

ETS和Mnesia表的最大数量.

命令行参数:

    -sname ejabberd

这个Erlang节点将只使用主机名的第一部分来指定, 即本域之外的其它Erlang节点不能够联系联络这个节点. 在大多数情况下这是更可取的选择.

    -name ejabberd

这个Erlang节点将被完全指定. 这只在你计划在不同的网络配置一个ejabberd集群时有用.

    -kernel inetrc ’"/etc/ejabberd/inetrc"’

指出使用名字解析的IP. 如果使用 -sname, 要么指定这个选项,要么指定 ERL_INETRC.

    -kernel inet_dist_listen_min 4200 inet_dist_listen_min 4210

定义 epmd 可以监听的第一个和最后一个端口.

    -detached

启动Erlang系统并从系统控制台分离. 运行守护进程和后台进程时有用.

    -noinput

确保Erlang系统不尝试读任何输入. 运行守护进程和后台进程时有用.

    -pa /var/lib/ejabberd/ebin

指定Erlang二进制文件(*.beam)所在目录.

    -s ejabberd

告诉Erlang运行时系统启动ejabberd应用.

    -mnesia dir ’"/var/lib/ejabberd/"’

指定Mnesia数据库目录.

    -sasl sasl_error_logger {file, "/var/log/ejabberd/erlang.log"}

Erlang/OTP系统日志文件的路径. 这里SASL意味着 系统架构支持库“System Architecture Support Libraries” 而不是 简单认证和安全层 “Simple Authentication and Security Layer”.

    +K [true|false]

内核轮询.

    -smp [auto|enable|disable]

SMP(多CPU)支持.

    +P 250000

Erlang进程的最大数量.

    -remsh ejabberd@localhost

在一个远程Erlang节点上打开一个Erlang shell.

    -hidden

到其它节点的连接是隐藏的(没有公开发布),结果是这个节点不被认为是集群的一部分. 当启动一个临时的ctl或debug节点的时候这是很重要的.

注意:当使用shell脚本的时候,需要避免使用一些字符, 例如 " 和 {}. 你可在Erlang手册页 (erl -man erl)找到其它选项.

二、ejabberd命令

一个ejabberd命令是一个通过名字指定的抽象函数, 该函数在ejabberd_commands服务里注册,并指定调用参数的编号和类型以及输出类型. 那些命令能被定义在任何Erlang模块里,并能使用任何合法的前端执行.

ejabberd包含一个前端用来执行ejabberd命令即脚本ejabberdctl. 其它已知可执行ejabberd命令的前端有: ejabberd_xmlrpc (XML-RPC 服务), mod_rest (HTTP POST 服务), mod_shcommands (ejabberd WebAdmin 页面).

1、ejabberd命令清单

ejabberd缺省包含了一些ejabberd命令. 当更多模块被安装时, 在前端又会有新命令可以用.

获得可用命令和帮助的最简单方法是使用ejabberdctl脚本:

$ ejabberdctl help

Usage: ejabberdctl [--node nodename] [--auth user host password] command [options]

Available commands in this ejabberd node:

backup file                 Store the database to backup file

connected_users              List all established sessions

connected_users_number       Get the number of established sessions

...

最令人感兴趣的是:

    reopen_log

在日志文件改名之后重新打开它们. 如果在调用此命令之前旧文件没有被改名, 则它们自动改名为 "*-old.log".关于这点后文书还会详述.

    backup ejabberd.backup

存储内部 Mnesia 数据库到一个二进制备份文件.

    restore ejabberd.backup

立刻从一个二进制文件恢复内部 Mnesia 数据库. 如果你有一个很大的数据库,这将消耗很多内存, 所以最好使用 install_fallback.

    install_fallback ejabberd.backup

将二进制备份文件安装程序fallback,这样,它将在下一次ejabberd启动的时候被用于恢复数据库. 这意味着, 在运行这个命令之后, 你不得不重启 ejabberd. 这个命令比restore需要更少的内存.

    dump ejabberd.dump

Dump内部的 Mnesia 数据库到一个文本文件 dump.

    load ejabberd.dump

立刻从一个文本文件dump恢复. 这不建议用于大数据库, 因为它将消耗很多时间、内存和cpu. 那种情况下更适合使用 backup 和 install_fallback.

    import_piefxis, export_piefxis, export_piefxis_host

这些选项可用于使用 XEP-0227 格式的 XML文件 从/到 另外一个 Jabber/XMPP 服务器迁移帐号或转移一个虚拟主机的用户到另一个 ejabberd 安装环境. 可以参见 ejabberd迁移工具.

    import_file, import_dir

这些选项可被用于迁移使用jabberd1.4格式的XML文件的帐户, 从其他 Jabber/XMPP 服务器. 已经有 从其他软件迁移到ejabberd的教程.

    delete_expired_messages

这个选项可被用于删除旧的离线消息. 当离线消息数量非常高的时候有用.

    delete_old_messages days

删除指定天数之前的离线消息.

    register user host password

在那个域用给定的密码注册一个帐号.

    unregister user host

注销给定帐号.

2、以AccessCommands限制执行

前端可能被配置成限制访问某些命令. 在那种情况下, 必须提供认证信息. 在每个前端 AccessCommands 选项被定义在不同的地方. 但是所有情况下这个选项的语法都是相同的:

AccessCommands = [ {Access, CommandNames, Arguments}, ...]

Access = atom()

CommandNames = all | [CommandName]

CommandName = atom()

Arguments = [ {ArgumentName, ArgumentValue}, ...]

ArgumentName = atom()

ArgumentValue = any()

缺省值是不定义任何限制: []. 当执行一个命令时提供认证信息, 这些信息为一个被允许执行相应命令的本地XMPP帐号的Username、Hostname和Password . 这意味着这个帐号必须在本地ejabberd已经注册, 因为这个信息将被验证. 可能提供纯文本密码或它的 MD5 哈希值.

当定义了一个或多个访问限制,并且提供了认证信息, 每个限制被验证直到某人完全符合: 这个帐号和 Access rule匹配, 命令名字列于 CommandNames 之中, 并且提供的参数和Arguments不抵触.

以下例子用来理解这个语法, 让我们假设那些选项:

{hosts, ["example.org"]}.

{acl, bots, {user, "robot1", "example.org"}}.

{access, commaccess, [{allow, bots}]}.

这个访问限制的列表只允许 robot1@example.org 执行所有命令:

[{commaccess, all, []}]

看看另一个限制列表 (相应的 ACL 和 ACCESS 没有显示):

[

%% 这个 bot 能执行所有命令:

{bot, all, []},

%% 这个 bot 只能执行命令 'dump'. 不限制参数:

{bot_backups, [dump], []} %% 这个 bot 可执行所有命令,

%% 但是如果使用 'host' 参数, 它必须是 "example.org":

{bot_all_example, all, [{host, "example.org"}]},

%% 这个 bot 只能执行命令 'register',

%% 并且如果使用参数 'host' , 它必须是 "example.org":

{bot_reg_example, [register], [{host, "example.org"}]},

%% 这个 bot 能执行命令 'register' 和 'unregister',

%% 如果使用参数 host , 它必须是 "test.org":

{_bot_reg_test, [register, unregister], [{host, "test.org"}]}

]

三、Web管理

ejabberd Web管理允许使用web浏览器管理大部分ejabberd.

这个功能缺省是激活的: 一个使用选项 web_admin 的 ejabberd_http 监听者被包含在监听的端口里. 然后你可以在你喜欢的wen浏览器里打开 http://server:port/admin/ . 你将被要求键入一个拥有管理员权限的ejabberd用户的 username (全 Jabber ID) 和 password . 在认证之后你将看到一个类似下图的页面.

Ejabberd源码解析前奏--管理

图1 Web管理

这里你可以编辑访问限制、管理用户、创建备份、管理数据库、允许/禁止监听的端口、查看服务器统计数据,…

access rule 配置决定那些帐号可以访问Web管理以及修改它. access rule webadmin_view 仅被授予查看权限: 那些帐号能以只读方式浏览Web管理.

示例配置:

(1)你可以把Web管理伺服于和HTTP 轮询界面相同的端口. 在这个了例子里你应该把你的web浏览器指向 http://example.org:5280/admin/ 来管理所有虚拟主机或指向 http://example.org:5280/admin/server/example.com/ 来管理虚拟主机 example.com. 在你访问Web管理之前,你需要键入用户信息,包括username、JID 和 password . 在这个例子里你可键入 username ‘admin@example.net’ 来管理所有虚拟主机 (第一个 URL). 如果你以‘admin@example.com’登录到http://example.org:5280/admin/server/example.com/,你只能管理虚拟主机 example.com. 帐号‘reviewer@example.com’可以只读模式浏览虚拟主机.

{acl, admins, {user, "admin", "example.net"}}.

{host_config, "example.com", [{acl, admins, {user, "admin", "example.com"}}]}.

{host_config, "example.com", [{acl, viewers, {user, "reviewer", "example.com"}}]}.

{access, configure, [{allow, admins}]}. {access, webadmin_view, [{allow, viewers}]}.

{hosts, ["example.org"]}.

{listen,

[

...

{5280, ejabberd_http, [http_poll, web_admin]},

...

]}.

(2)因为安全的原因, 你可以在一个安全的连接上伺服Web管理, 在一个不同于HTTP轮询接口的端口上, 并把它绑定到内部的局域网IP. 这个Web管理将只能被浏览器从https://192.168.1.1:5282/admin/ 访问:

{hosts, ["example.org"]}.

{listen,

[

...

{5280, ejabberd_http, [

http_poll

]},

{{5282, "192.168.1.1"}, ejabberd_http, [

web_admin,

tls, {certfile, "/usr/local/etc/server.pem"}

]},

...

]}.

在ejabberd Web管理页面中包含了一个到 ejabberd安装和操作指南 相关章节的连接. 为了查看这些链接, 本指南的一个 HTML 格式的拷贝必须安装在该系统上. 该文件缺省放在 "/share/doc/ejabberd/guide.html". 该文档的目录可以用环境变量 EJABBERD_DOC_PATH 来指定.

四、特设命令

如果你激活了 mod_configure 和 mod_adhoc, 你可以使用一个 XMPP 客户端在 ejabberd 上执行很多管理任务. 该客户端必须支持 Ad-Hoc Commands (XEP-0050), 而你必须以一个拥有适当权限的帐号登录到该 XMPP 服务器.

五、修改计算机主机名

ejabberd使用分布式的 Mnesia 数据库. 作为分布式数据库, Mnesia 强制它的文件一致性, 所以它在它里面存储Erlang节点名. 一个Erlang节点的名字包含了该计算机的hostname. 所以, 如果你修改ejabberd运行的机器的名字,或当你移动ejabberd到一个不同的机器上时,那么Erlang节点名也修改了.

你有两个办法在一个新节点名的 ejabberd 上使用旧的 Mnesia 数据库: 把旧节点名写入 ejabberdctl.cfg, 或转换数据库到为新节点名.

那些例子步骤将备份, 转换并装载 Mnesia 数据库. 你需要要么有旧的 Mnesia spool 目录,要么有一个 Mnesia 的备份. 如果你已经有一个旧的数据库的备份文件, 你可以直接去步骤5. 你也需要知道旧节点名和新节点名. 如果你不知道它们, 执行ejabberdctl或在ejabberd 日志文件里查找它们.

在开始之前, 设置一些变量:

OLDNODE=ejabberd@oldmachine

NEWNODE=ejabberd@newmachine

OLDFILE=/tmp/old.backup

NEWFILE=/tmp/new.backup

(1)强制以旧节点名启动 ejabberd :

ejabberdctl --node $OLDNODE start

(2)生成一个备份文件:

ejabberdctl --node $OLDNODE backup $OLDFILE

(3)停止旧节点:

ejabberdctl --node $OLDNODE stop

(4)确保在 Mnesia spool 目录没有文件 . 例如:

mkdir /var/lib/ejabberd/oldfiles

mv /var/lib/ejabberd/*.* /var/lib/ejabberd/oldfiles/

(5)启动 ejabberd. 不需要再指定任何节点名:

ejabberdctl start

(6)转换备份到新节点名:

ejabberdctl mnesia_change_nodename $OLDNODE $NEWNODE $OLDFILE $NEWFILE

(7)安装备份文件作为一个fallback:

ejabberdctl install_fallback $NEWFILE

(8)停止 ejabberd:

ejabberdctl stop

你可能在日志文件看到一个错误信息, 这是正常的, 不要担心:

Mnesia(ejabberd@newmachine):

** ERROR ** (ignoring core)

** FATAL ** A fallback is installed and Mnesia must be restarted.

Forcing shutdown after mnesia_down from ejabberd@newmachine...

(9)现在你可以最后启动 ejabberd:

ejabberdctl start

(10)检查是否旧数据库的信息可用: accounts, rosters... 完成之后, 记住从公共目录删除临时备份文件.