跳转到内容

配置数据库:config.xml 与 omv-confdbadm ​

OMV 在 Web 界面里做的所有设置,都先写进同一个 XML 文件,再由「应用」把它变成真正的配置文件。读完这一篇,你能读懂这个文件的结构,用 omv-confdbadm 安全地查询,知道什么时候才需要修改它,以及改坏了怎么退回去。

开始之前 ​

  • 命令在 OMV 的 shell(root 身份)里执行。
  • 只想知道某项设置现在是什么,用只读命令就够了,下面「读取」一节没有风险。
  • 想修改的话,先看「修改」一节的警示块,并准备好系统盘备份。

数据库是什么 ​

配置数据库就是 /etc/openmediavault/config.xml。它的权限是 660,属组是 openmediavault-config,所以只有 root 和这个组的成员能读写;Web 界面的后台进程(openmediavault-webgui 用户)就在这个组里。

里面放什么 ​

文件的顶层结构来自安装时使用的模板 /usr/share/openmediavault/templates/config.xml:

节点内容
system系统级设置:软件更新、电源管理、监测、时间、邮件与通知、证书、网络、用户设置、计划任务、远程日志、文件系统挂载条目(fstab)、共享文件夹
webadminWeb 管理界面:端口、HTTPS、证书引用、自动注销时间
services各项服务:SSH、NFS、S.M.A.R.T.、SMB、Rsync,以及插件自己加的节点

模板里有两句注释:system 和 webadmin 下「不要在这里添加任何配置」,services 是「插件配置区」。

不放什么 ​

  • 用户和组本身不在这里。 Linux 账户的 UID、密码、组成员关系在系统的 /etc/passwd、/etc/shadow、/etc/group 里,数据库只补充邮箱、SSH 公钥、是否禁止修改账户和组的备注。所以只恢复 config.xml 并不会让用户回来。
  • 数据本身不在这里。 文件、RAID 元数据、文件系统内容都在磁盘上。数据库只记录「某个共享文件夹 = 某个文件系统 UUID + 相对路径」。

数据库里有明文密码

SMTP 密码、代理密码、rsync 模块用户的密码、Wi-Fi 密钥和证书私钥都以明文保存在 config.xml 里。给它做备份时按机密文件对待(权限 600,放在只有自己能读的位置),不要把整个文件贴到论坛或工单里。

数据模型 ​

每一种配置对象都有一个 JSON 描述文件,放在 /usr/share/openmediavault/datamodels/,文件名以 conf. 开头。它定义了这个对象在 XML 里的位置(XPath)、每个属性的类型、取值范围和默认值。

以 SSH 为例,conf.service.ssh.json 说明它对应 .//services/ssh,只有一份(不可迭代),属性有 enable、port(默认 22)、permitrootlogin(默认 true)等。共享文件夹 conf.system.sharedfolder 对应 .//system/shares/sharedfolder,是可迭代对象,每一项用 uuid 标识。

对象之间用 UUID 互相引用。例如共享文件夹的 mntentref 指向 fstab 里某个文件系统挂载条目的 uuid,SMB 共享的 sharedfolderref 指向共享文件夹的 uuid。

读取 ​

omv-confdbadm 的 list-ids 列出所有数据模型 ID,read 读取对象并输出 JSON,exists 用退出码告诉你对象是否存在。这三个子命令都是只读的。

sh
omv-confdbadm list-ids
omv-confdbadm read --prettify conf.service.ssh
omv-confdbadm read --prettify conf.system.sharedfolder
omv-confdbadm read conf.system.sharedfolder --uuid <共享文件夹的 UUID>
omv-confdbadm read --defaults conf.service.ssh
  • 不可迭代的对象返回一个 JSON 对象,可迭代的对象返回一个数组。
  • --defaults 打印数据模型里定义的默认值,不读数据库。官方插件的安装脚本就这样用它来创建默认配置,例如 SNMP 插件:omv-confdbadm read --defaults "conf.service.snmp" | omv-confdbadm update "conf.service.snmp" -。
  • 按 UUID 找不到对象时,read 报错并以非零退出码结束。

过滤 ​

--filter 接受一段 JSON,用 operator、arg0、arg1 描述条件。源码里支持的运算符有:and、or、not、stringEquals、stringNotEquals、stringContains、stringStartsWith、stringEnum、equals、notEquals、less、greater、lessEqual、greaterEqual。

sh
# 所有 Btrfs 文件系统的挂载条目
omv-confdbadm read conf.system.filesystem.mountpoint \
  --filter '{"operator":"stringEquals","arg0":"type","arg1":"btrfs"}'

# 数据库里有没有 Btrfs 文件系统?看退出码
omv-confdbadm exists conf.system.filesystem.mountpoint \
  --filter '{"operator":"stringEquals","arg0":"type","arg1":"btrfs"}' && echo 有

omv-confdbadm 的输出是 JSON,配合 OMV 自带的 jq 处理最方便:

sh
# 列出所有共享文件夹的名字和相对路径
omv-confdbadm read conf.system.sharedfolder | jq -r '.[] | "\(.name)\t\(.reldirpath)"'

修订文件:界面里的「撤销」是怎么实现的 ​

在 Web 界面里保存设置时,OMV 的后台会在写入前把当前的 config.xml 复制一份,命名为 config.xml.0001、config.xml.0002……(权限 600,放在同一目录)。这些文件有两个用途:

  • 界面里的撤销(Undo):用最早的那个修订文件覆盖回 config.xml,并清空待应用列表。
  • omv-firstaid 的 Restore configuration backup:取编号最大的那个修订文件,显示和当前文件的差异,确认后覆盖回去。

点击应用成功后,所有修订文件都会被删除。所以:

  • 它们只存在于「已保存但还没应用」的这段时间里,不是长期备份。
  • 看到 config.xml.0001 这样的文件,说明有未应用的更改。
  • omv-confdbadm 写入时不会产生修订文件。

长期的配置备份要自己做,见 OMV 配置怎么留底。

修改 ​

直接改数据库会绕过界面的所有保护

影响范围:配置写坏会让 omv-engined、Web 界面和相关服务无法启动或无法部署,严重时需要用 omv-firstaid 或备份恢复。命令行改数据库不会替你做界面和 RPC 会做的其他事,例如创建 Linux 用户、创建共享文件夹的目录、检查对象是否被引用。

前置条件:改之前备份 config.xml;界面里没有待应用的更改(黄色提示条不在,omv-salt deploy list-dirty 输出 No dirty states found.);最好先在测试机上演练。

怎么回退:把备份复制回 /etc/openmediavault/config.xml,确认权限仍是 660、属组 openmediavault-config,再重新部署受影响的模块。

能用界面或 RPC 解决的,不要走这里。三种方式从稳妥到危险依次是:

  1. 界面或 omv-rpc:有参数校验,会触发模块标记为待应用,会执行创建用户、创建目录这类附带动作。见 omv-rpc 与 JSON-RPC 接口。
  2. omv-confdbadm update:有数据模型校验(类型、取值范围),但不触发任何附带动作,也不会标记待应用。
  3. 手工编辑 XML:没有任何校验,也是最容易写坏文件的方式。

用 omv-confdbadm 修改一项设置 ​

下面的例子把 SMB 的服务器描述(serverstring)改成 OMV NAS,这个改动无害,也容易还原。

sh
# 1. 备份,权限 600
install -m 600 /etc/openmediavault/config.xml /root/config.xml.$(date +%Y%m%d-%H%M%S)

# 2. 看当前值,并记下共享的数量,改完之后核对
omv-confdbadm read conf.service.smb | jq '{workgroup, serverstring, shares: (.shares.share | length)}'

# 3. 读出完整对象,改一个字段,再写回
omv-confdbadm read conf.service.smb | jq '.serverstring = "OMV NAS"' \
  | omv-confdbadm update conf.service.smb -

最后一行有两个要点:

  • update 写入的是整个对象。 它先按数据模型加载默认值,再套上你给的 JSON,最后替换数据库里的整个节点。只传你想改的那个字段,其余字段会被重置为默认值。所以一定先 read 出完整对象,改完再写回。
  • - 表示从标准输入读取 JSON。
  • update 替换的是数据库里的整个节点,包括节点下面的子项。 conf.service.smb 的数据模型把 shares(所有 SMB 共享)也包含在内,所以 read 出来的 JSON 里有全部共享,原样写回不会丢。换成别的对象之前,先确认 read 的输出里包含了它下面所有的子项,数据模型之外的内容,update 之后会消失。

另外,备份文件放在 /root,不要放进 /etc/openmediavault/。OMV 应用配置成功后,会删除那个目录里所有以 config.xml. 开头的文件,把它们当成修订文件,你的备份也会被一起删掉。

让改动生效 ​

omv-confdbadm 不会通知任何模块,界面也不会出现黄色提示条。有两种办法让它生效。

办法一:标记待应用,再在界面点应用。 你能在界面上看到有哪些模块被改动,走的是和平时完全一样的部署路径:

sh
. /usr/share/openmediavault/scripts/helper-functions
omv_module_set_dirty samba

然后在 Web 界面点击黄色提示条上的应用。

办法二:直接部署。 不依赖界面:

sh
omv-salt deploy run samba

samba 是 SMB 对应的 Salt 模块名。模块名可以用 omv-salt deploy list 查看,也可以在界面「应用」完成后的通知里看到更新了哪些模块。部署会重启对应的服务,SMB 客户端会短暂断开。

删除和新建 ​

  • omv-confdbadm delete <ID> --uuid <UUID> 或 --filter '<JSON>' 删除对象,成功时输出删除了多少个对象。它不检查引用:删除一个仍被共享文件夹引用的文件系统条目,会留下悬空引用。删除前先 read 确认对象,必要时用 exists 检查有没有别的对象的 ...ref 指向它。
  • 新建可迭代对象时,把 uuid 设为 fa4b1c66-ef79-11e5-87a0-0002b3a176b4(OMV 保留的「新对象」UUID),update 会替你生成真正的 UUID。但共享文件夹、用户这类对象请走 RPC,因为 RPC 还会创建目录、创建系统账户。

手工编辑 XML 的流程 ​

只有前两种方式都做不到时才这样做,例如要批量搬动大量设置。

  1. 按上面的方法备份。
  2. 编辑 /etc/openmediavault/config.xml,保持结构和缩进。
  3. 检查格式是否正确:xmlstarlet val -w /etc/openmediavault/config.xml。
  4. 检查数据库还能被 OMV 读取:omv-confdbadm read conf.service.ssh > /dev/null && echo OK。
  5. 确认权限:ls -l /etc/openmediavault/config.xml,应该是 660、属组 openmediavault-config。
  6. 按「让改动生效」部署受影响的模块。

此外要知道两点:

  • omv-confdbadm 写文件时直接覆盖原文件,并且不使用后台(PHP)那套互斥锁,所以不要在界面正在保存设置的同时运行它。
  • 升级时,安装包会用 omv-confdbadm migrate 对数据库运行迁移脚本。数据库结构被你手工改乱,会让迁移失败。

检查结果 ​

用只读命令确认改动已经写进数据库并且部署到了系统:

sh
omv-confdbadm read conf.service.smb | jq -r .serverstring   # 数据库里的值
omv-confdbadm read conf.service.smb | jq '.shares.share | length'   # 共享数量应与修改前一致
grep 'server string' /etc/samba/smb.conf                      # 部署后生成的配置文件(只读查看)
omv-salt deploy list-dirty                                    # 没有遗留的待应用模块

常见问题 ​

改完数据库,界面上的值没有变。 界面每次都会重新读取数据库,值没变通常是浏览器缓存,刷新页面。如果刷新后仍是旧值,确认改的是正确的数据模型 ID,并且 update 没有报错。

update 报 No valid JSON。 JSON 里有语法错误,例如引号配对不对。用 jq . <<< '<JSON>' 先检查。

改完以后界面报错、服务起不来。 先用备份恢复,再重新部署:

sh
install -m 660 -g openmediavault-config /root/config.xml.<备份时间> /etc/openmediavault/config.xml
omv-salt deploy run <模块>

如果连 omv-rpc 都不能用,用 omv-firstaid 处理,见 omv-firstaid 救援工具。

参考资料 ​

OpenMediaVault 非官方中文使用指南,与 openmediavault 项目及其开发者无隶属关系。