ownCloud oCIS 常用 CLI 命令详解
ownCloud oCIS 常用 CLI 命令实践篇:ocis 主命令树、version/list/init 信息查看与初始化、备份与存储维护(trash/revisions/backup/decomposedfs/shares)、迁移(migrate)、基准测试(benchmark)子命令参数与真实回显,Graph API 与 LDAP 双路线用户管理实测(含 LDAP 绑定 49 排障全记录)。
ownCloud oCIS 常用 CLI 命令详解
目标:把 ownCloud Infinite Scale(oCIS)唯一的管理入口——
ocis命令行工具讲透:主命令树、信息查看、初始化、备份与存储维护、迁移、基准测试的子命令与参数(全部参数取自--help实测回显,默认值照抄真实输出),并给出两条用户管理路线(Graph API / LDAP)的逐条输入与实测输出。本文与部署篇、配置篇同属一个系列:安装过程见《Ubuntu 22.04 安装 ownCloud oCIS 指南》,环境变量见《ownCloud oCIS 配置参数详解》。本文全部命令均于 2026-10-22 在真实服务器上逐条执行,输出逐行照抄实测回显。
一、环境信息
| 项目 | 取值 |
|---|---|
| 服务器操作系统 | Ubuntu 22.04 LTS(x86_64) |
| 服务器 IP | 10.89.61.3 |
| oCIS 版本 | 8.1.0+730d9a04(Production 通道,编译于 2026-07-06) |
| 部署方式 | 单二进制 /usr/local/bin/ocis + systemd 托管(ocis.service),配置目录 /etc/ocis,数据目录 /var/lib/ocis |
| 管理员账号 | admin / q1w2e3r4 |
| 实测日期 | 2026-10-22 |
ocis version --skip-services 实测输出(跳过对运行中服务的逐一询问,只打印本二进制版本):
Version: 8.1.0+730d9a04
Compiled: 2026-07-06 00:00:00 +0000 UTC
💡 oCIS 8.x 存在 Production(约每 6 个月)与 Rolling(约每 3 周)两条发布通道,版本选型依据见《ownCloud 介绍与选型指南》;
ocis是一个静态链接的 Go 单二进制,不依赖 PHP、数据库等外部组件。
二、工具概览
2.1 主命令树
ocis --help 实测输出(原样沉淀):
NAME:
ocis - ownCloud Infinite Scale
USAGE:
ocis [global options] command [command options]
AUTHOR:
ownCloud GmbH <support@owncloud.com>
COMMANDS:
backup ocis backup functionality
init initialise an ocis config
revisions ocis revisions functionality
trash ocis trash functionality
help, h Shows a list of commands or help for one command
benchmark:
benchmark cli tools to test low and high level performance
fullstack:
server start a fullstack server (runtime and all services in supervised mode)
info:
version print the version of this binary and all running service instances
maintenance:
decomposedfs cli tools to inspect and manipulate a decomposedfs storage.
shares CLI tools to manage entries in the share manager.
migration:
migrate migrate data from an existing to another instance
runtime:
list list oCIS services running in the runtime (supervised mode)
services:
activitylog activitylog service commands
antivirus antivirus service commands
app-provider app-provider service commands
app-registry app-registry service commands
audit audit service commands
auth-app auth-app service commands
auth-basic auth-basic service commands
auth-bearer auth-bearer service commands
auth-machine auth-machine service commands
auth-service auth-service service commands
clientlog clientlog service commands
collaboration collaboration service commands
eventhistory eventhistory service commands
frontend frontend service commands
gateway gateway service commands
graph graph service commands
groups groups service commands
idm idm service commands
idp idp service commands
invitations invitations service commands
nats nats service commands
notifications notifications service commands
ocdav ocdav service commands
ocm ocm service commands
ocs ocs service commands
policies policies service commands
postprocessing postprocessing service commands
proxy proxy service commands
search search service commands
settings settings service commands
sharing sharing service commands
sse sse service commands
storage-publiclink storage-publiclink service commands
storage-shares storage-shares service commands
storage-system storage-system service commands
storage-users storage-users service commands
thumbnails thumbnails service commands
userlog userlog service commands
users users service commands
web web service commands
webdav webdav service commands
webfinger webfinger service commands
GLOBAL OPTIONS:
--help, -h show help
2.2 命令分类速查表
| 类别(help 中分组) | 真实命令名 | 用途 |
|---|---|---|
| info | ocis version | 打印二进制版本与运行中服务版本 |
| runtime | ocis list | 列出运行时正在监管的服务清单 |
| fullstack | ocis server | 前台启动 runtime + 全部服务(supervised 模式) |
| services | ocis <服务名> | 单独启动某个服务(40+ 个,如 ocis idm) |
| maintenance | ocis decomposedfs / ocis shares | 存储元数据检查 / 共享管理器维护 |
| migration | ocis migrate | 存储与共享数据迁移 |
| — | ocis backup / ocis trash / ocis revisions | 备份一致性检查 / 回收站与历史版本清理 |
| benchmark | ocis benchmark | HTTP 与系统调用基准测试 |
| — | ocis init | 初始化生成 ocis.yaml 配置 |
⚠️ 注意:
maintenance、migration、fullstack只是--help里的分组标题,不是可执行的命令。实测执行ocis maintenance decomposedfs --help会得到No help topic for 'maintenance';真正的命令名是ocis decomposedfs、ocis shares、ocis migrate、ocis server。这是照抄官方文档示例时最容易踩的第一个坑。
三、前置条件
- 服务已由 systemd 托管并运行:
systemctl status ocis为 active,服务单元与ocis init初始化过程见《Ubuntu 22.04 安装 ownCloud oCIS 指南》; - 环境变量来源:生产部署通过
/etc/ocis/ocis.env(systemdEnvironmentFile)注入OCIS_CONFIG_DIR、OCIS_BASE_DATA_PATH等变量,各变量逐项含义见《ownCloud oCIS 配置参数详解》; ocis在 PATH 中:本文安装路径为/usr/local/bin/ocis;- LDAP 查询工具:用户管理 LDAP 路线需要
ldap-utils包(安装命令见 10.2 节); - 读取 ocis.yaml 的权限:部分维护命令需要从
/etc/ocis/ocis.yaml读取服务账号口令,该文件含全部密钥,务必chmod 600并仅限管理员读取。
四、信息查看命令
4.1 ocis version
ocis version --help 实测输出:
NAME:
ocis version - print the version of this binary and all running service instances
USAGE:
ocis version [command options]
CATEGORY:
info
OPTIONS:
--skip-services skip service listing (default: false)
--help, -h show help
不带 --skip-services 执行 ocis version 时,会先打印二进制版本,再输出一张"运行中服务"表格(实测输出节选,表格共列出全部在运行服务,此处截取前两行以示格式):
Version: 8.1.0+730d9a04
Compiled: 2026-07-06 00:00:00 +0000 UTC
┌────────────────┬────────────────┬────────────────────────────────────────────────────────────────────┐
│ VERSION │ ADDRESS │ ID │
├────────────────┼────────────────┼────────────────────────────────────────────────────────────────────┤
│ 8.1.0+730d9a04 │ 127.0.0.1:9164 │ com.owncloud.api.app-provider-a6c82132-9c64-4bb6-8479-9254c8c0526a │
│ 10.11.0 │ 127.0.0.1:9350 │ com.owncloud.web.ocdav-a6c82132-9c64-4bb6-8479-9254c8c0526a │
└────────────────┴────────────────┴────────────────────────────────────────────────────────────────────┘
💡 注意 ocdav 服务显示的是协议版本
10.11.0(ownCloud WebDAV 协议版本号),不是 oCIS 版本;每个服务实例的 ID 由服务名-实例 UUID组成。排查"某服务是否跑起来"时,这张表比逐个看端口直观。
4.2 ocis list
ocis list --help 实测输出:
NAME:
ocis list - list oCIS services running in the runtime (supervised mode)
USAGE:
ocis list [command options]
CATEGORY:
runtime
OPTIONS:
--hostname value (default: "localhost") [$OCIS_RUNTIME_HOST]
--port value (default: "9250") [$OCIS_RUNTIME_PORT]
--help, -h show help
实测输出(本机共 34 个服务在运行):
┌────────────────────┐
│ SERVICE │
├────────────────────┤
│ activitylog │
│ app-provider │
│ app-registry │
│ auth-basic │
│ auth-machine │
│ auth-service │
│ clientlog │
│ eventhistory │
│ frontend │
│ gateway │
│ graph │
│ groups │
│ idm │
│ idp │
│ nats │
│ ocdav │
│ ocm │
│ ocs │
│ postprocessing │
│ proxy │
│ search │
│ settings │
│ sharing │
│ sse │
│ storage-publiclink │
│ storage-shares │
│ storage-system │
│ storage-users │
│ thumbnails │
│ userlog │
│ users │
│ web │
│ webdav │
│ webfinger │
└────────────────────┘
ocis list 通过 runtime 的 HTTP 接口(默认 localhost:9250,可用 OCIS_RUNTIME_PORT 覆盖)查询,因此只能在服务所在主机上执行。
五、初始化命令 ocis init
ocis init --help 实测输出:
NAME:
ocis init - initialise an ocis config
USAGE:
ocis init [command options]
OPTIONS:
--insecure value Allow insecure oCIS config (default: "ask") [$OCIS_INSECURE]
--diff, -d Show the difference between the current config and the new one (default: false)
--force-overwrite, -f Force overwrite existing config file (default: false) [$OCIS_FORCE_CONFIG_OVERWRITE]
--config-path value Config path for the ocis runtime (default: "/root/.ocis/config") [$OCIS_CONFIG_DIR, $OCIS_BASE_DATA_PATH]
--admin-password value, --ap value Set admin password instead of using a random generated one [$ADMIN_PASSWORD, $IDM_ADMIN_PASSWORD]
--help, -h show help
参数要点(默认值逐项取自上方实测回显):
| 参数 | 默认值 | 说明 |
|---|---|---|
--insecure | ask(交互询问) | 允许生成不安全(自签名/HTTP)配置;脚本化安装用 ocis init --insecure true 跳过询问 |
--diff | false | 与现有配置做差异比较后输出 |
--force-overwrite / -f | false | 覆盖已存在的 ocis.yaml,对应环境变量 OCIS_FORCE_CONFIG_OVERWRITE |
--config-path | /root/.ocis/config | 配置目录;受 OCIS_CONFIG_DIR 影响(生产建议 /etc/ocis) |
--admin-password / --ap | 随机生成 | 指定管理员口令,对应 ADMIN_PASSWORD、IDM_ADMIN_PASSWORD |
初始化的完整实测过程(四行回显块、生成的 ocis.yaml 结构)已在《Ubuntu 22.04 安装 ownCloud oCIS 指南》中逐步记录,此处不再重复。
六、数据维护命令(trash / revisions / backup)
这一组命令直接操作 decomposedfs 存储目录,执行前应停止 oCIS 服务(至少避免用户写入),且三者都内置了安全阀。
6.1 ocis trash purge-empty-dirs(清理空目录)
ocis trash purge-empty-dirs --help 实测输出:
NAME:
ocis trash purge-empty-dirs - purge empty directories
USAGE:
ocis trash purge-empty-dirs [command options]
OPTIONS:
--basepath value, -p value the basepath of the decomposedfs (e.g. /var/tmp/ocis/storage/users)
--dry-run do not delete anything, just print what would be deleted (default: true)
--help, -h show help
--basepath 指向 decomposedfs 的 users 存储(本文环境即 /var/lib/ocis/storage/users);--dry-run 默认就是 true——不显式加 --dry-run=false 它只打印将删除的内容,不会真正删除。
6.2 ocis revisions purge(清理历史版本)
ocis revisions purge --help 实测输出:
NAME:
ocis revisions purge - purge revisions
USAGE:
ocis revisions purge [command options]
OPTIONS:
--basepath value, -p value the basepath of the decomposedfs (e.g. /var/tmp/ocis/storage/metadata)
--blobstore value, -b value the blobstore type. Can be (none, ocis, s3ng). Default ocis. Note: When using s3ng this needs same configuration as the storage-users service (default: "ocis")
--dry-run do not delete anything, just print what would be deleted (default: true)
--verbose, -v print verbose output (default: false)
--resource-id value, -r value purge all revisions of this file/space. If not set, all revisions will be purged
--glob-mechanism value the glob mechanism to find all nodes. Can be 'glob', 'list' or 'workers'. 'glob' uses globbing with a single worker. 'workers' spawns multiple go routines, accelatering the command drastically but causing high cpu and ram usage. 'list' looks for references by listing directories with multiple workers. Default is 'glob' (default: "glob")
--help, -h show help
参数要点:
--blobstore有none / ocis / s3ng三种,默认ocis(本地 blob 存储);若部署采用 s3ng(S3 后端),必须与 storage-users 服务的配置一致;--resource-id可以只清某个文件/空间的版本,不指定则清全部;--glob-mechanism决定扫描方式:glob(默认,单 worker)、workers(多协程并行,快但 CPU/内存占用高)、list(按目录列举);- 同样默认
--dry-run true。
6.3 ocis backup consistency(备份一致性检查)
ocis backup consistency --help 实测输出:
NAME:
ocis backup consistency - check backup consistency
USAGE:
ocis backup consistency [command options]
OPTIONS:
--basepath value, -p value the basepath of the decomposedfs (e.g. /var/tmp/ocis/storage/users)
--blobstore value, -b value the blobstore type. Can be (none, ocis, s3ng). Default ocis (default: "ocis")
--fail exit with non-zero status if consistency check fails (default: false)
--help, -h show help
用于核对"元数据与实际 blob 文件"的一致性;--fail 让检查失败时以非零退出码结束,适合放进 cron/Nagios 类巡检脚本做判断。
七、存储维护命令(decomposedfs / shares)
7.1 ocis decomposedfs(存储元数据检查与修复)
ocis decomposedfs metadata --help 实测输出:
NAME:
ocis decomposedfs metadata - cli tools to inspect and manipulate node metadata
USAGE:
ocis decomposedfs metadata [command options]
COMMANDS:
dump print the metadata of the given node. String attributes will be enclosed in quotes. Binary attributes will be returned encoded as base64 with their value being prefixed with '0s'.
get print a specific attribute of the given node. String attributes will be enclosed in quotes. Binary attributes will be returned encoded as base64 with their value being prefixed with '0s'.
set manipulate metadata of the given node. Binary attributes can be given hex encoded (prefix by '0x') or base64 encoded (prefix by '0s').
help, h Shows a list of commands or help for one command
OPTIONS:
--root value, -r value Path to the decomposedfs
--node value, -n value Path to or ID of the node to inspect
--help, -h show help
dump / get / set 三个子命令分别对应"打印节点全部元数据 / 读取单个属性 / 修改属性",--root 指定存储根目录,--node 传节点路径或节点 ID。这是深排障(例如某文件元数据损坏)时才用的底层工具。
ocis decomposedfs check-treesize --help 实测输出:
NAME:
ocis decomposedfs check-treesize - cli tool to check the treesize metadata of a Space
USAGE:
ocis decomposedfs check-treesize [command options]
OPTIONS:
--root value, -r value Path to the root directory of the decomposedfs
--node value, -n value Space ID of the Space to inspect
--repair Try to repair nodes with incorrect treesize metadata. IMPORTANT: Only use this while ownCloud Infinite Scale is not running. (default: false)
--force Do not prompt for confirmation when running in repair mode. (default: false)
--help, -h show help
用于核对/修复空间配额统计值(treesize);帮助原文特别强调:--repair 只能在 oCIS 完全停止的状态下执行,否则统计值会被运行中的服务再次写坏。
7.2 ocis shares(共享管理器维护)
这一组命令面向 share manager(8.x 默认为 jsoncs3),实测三个子命令的 help:
NAME:
ocis shares cleanup - Clean up stale entries in the share manager.
USAGE:
ocis shares cleanup [command options]
OPTIONS:
--service-account-id value Name of the service account to use for the cleanup [$OCIS_SERVICE_ACCOUNT_ID]
--service-account-secret value Secret for the service account [$OCIS_SERVICE_ACCOUNT_SECRET]
--help, -h show help
NAME:
ocis shares clean-orphaned-grants - Detect and clean orphaned share-manager grants.
USAGE:
ocis shares clean-orphaned-grants [command options]
OPTIONS:
--service-account-id value Name of the service account to use for the scan [$OCIS_SERVICE_ACCOUNT_ID]
--service-account-secret value Secret for the service account [$OCIS_SERVICE_ACCOUNT_SECRET]
--space-id value Limit the scan to a specific storage space (opaque ID)
--dry-run Dry run mode enabled (default: true)
--force Force removal of suspected orphans even when listing shares fails (default: false)
--verbose, -v Verbose logging enabled (default: false)
--help, -h show help
NAME:
ocis shares move-stuck-upload-blobs - Move stuck upload blobs to the jsoncs3 share-manager metadata
USAGE:
ocis shares move-stuck-upload-blobs [command options]
OPTIONS:
--dry-run Dry run mode enabled (default: false)
--basepath value, -p value the basepath of the decomposedfs (e.g. /var/tmp/ocis/storage/users)
--filename value File to move from uploads/ to share manager metadata blobs/ (default: "received.json")
--verbose, -v Verbose logging enabled (default: false)
--help, -h show help
参数要点:
cleanup与clean-orphaned-grants需要服务账号凭据:OCIS_SERVICE_ACCOUNT_ID/OCIS_SERVICE_ACCOUNT_SECRET,取值就是 ocis.yaml 中proxy.service_account段的service_account_id与service_account_secret(本环境实测该段存在于 yaml,可直接 grep 取用);clean-orphaned-grants默认--dry-run true,先扫后删;--force允许在列举共享失败时仍强制删除疑似孤儿授权,慎用。
八、迁移命令 ocis migrate
8.1 ocis migrate decomposedfs
ocis migrate decomposedfs --help 实测输出:
NAME:
ocis migrate decomposedfs - run a decomposedfs migration
USAGE:
ocis migrate decomposedfs [command options]
COMMANDS:
list list decomposedfs migrations
help, h Shows a list of commands or help for one command
OPTIONS:
--direction value, -d value direction of the migration to run ('migrate' or 'rollback') (default: "migrate")
--migration value, -m value ID of the migration to run
--root value, -r value Path to the root directory of the decomposedfs
--help, -h show help
decomposedfs 的数据结构升级通过编号迁移脚本完成:ocis migrate decomposedfs list 先列出可用迁移,-m <ID> 指定要执行的迁移,-d rollback 回滚。
8.2 ocis migrate shares / publicshares
两个命令的 help 实测输出:
NAME:
ocis migrate shares - migrates shares from the previous to the new share manager
USAGE:
ocis migrate shares [command options]
OPTIONS:
--from value Share manager to export the data from (default: "json")
--to value Share manager to import the data into (default: "jsoncs3")
--help, -h show help
NAME:
ocis migrate publicshares - migrates public shares from the previous to the new public share manager
USAGE:
ocis migrate publicshares [command options]
OPTIONS:
--from value Public share manager to export the data from (default: "json")
--to value Public share manager to import the data into (default: "jsoncs3")
--help, -h show help
两者默认值 --from json --to jsoncs3 印证了 8.x 的默认共享管理器已是 jsoncs3——这组命令主要用于从旧版(json 管理器)升级时搬迁共享/对外链接数据。
8.3 ocis migrate rebuild-jsoncs3-indexes
NAME:
ocis migrate rebuild-jsoncs3-indexes - rebuild the share indexes from the shares json
USAGE:
ocis migrate rebuild-jsoncs3-indexes [command options]
OPTIONS:
--help, -h show help
当 jsoncs3 共享索引出现不一致时,从共享 json 原始数据重建索引,无任何参数。
九、基准测试命令 ocis benchmark
9.1 ocis benchmark client(HTTP 压测)
ocis benchmark client --help 实测输出:
NAME:
ocis benchmark client - Start a client that continuously makes web requests and prints stats. The options mimic curl, but URL must be at the end.
USAGE:
ocis benchmark client [command options]
CATEGORY:
benchmark
OPTIONS:
--request value, -X value Specifies a custom request method to use when communicating with the HTTP server. (default: "PROPFIND")
--user value, -u value Specify the user name and password to use for server authentication. (default: "admin:admin")
--insecure, -k Skip the TLS verification step and proceed without checking. (default: false)
--data value, -d value Sends the specified data in a request to the HTTP server.
--header value, -H value [ --header value, -H value ] Extra header to include in information sent.
--rate value Specify the maximum transfer frequency you allow a client to use - in number of transfer starts per time unit (sometimes called request rate).
The request rate is provided as "N/U" where N is an integer number and U is a time unit. Supported units are 's' (second), 'm' (minute), 'h' (hour) and 'd' /(day, as in a 24 hour unit). The default time unit, if no "/U" is provided, is number of transfers per hour.
--bearer-token-command value Command to execute for a bearer token, e.g. 'oidc-token OCIS'. When set, disables basic auth.
--every value Aggregate stats every time this amount of seconds has passed. (default: 0)
--jobs value, -j value Number of parallel clients to start. (default: 1)
--help, -h show help
典型用法(对 WebDAV 端点做 PROPFIND 压测,参数风格与 curl 一致):
ocis benchmark client -k -u admin:q1w2e3r4 -X PROPFIND \
-H 'Content-Type: application/xml' \
https://10.89.61.3:9200/remote.php/dav/files/admin/
注意三个真实默认值:请求方法默认 PROPFIND、Basic 认证默认 admin:admin(与本环境口令不同,务必显式 -u)、并发默认 1。
9.2 ocis benchmark syscalls(系统调用压测)
NAME:
ocis benchmark syscalls - test the performance of syscalls
USAGE:
ocis benchmark syscalls [command options]
CATEGORY:
benchmark
OPTIONS:
--path value Path to test
--iterations value Number of iterations to execute (default: "100")
--help, -h show help
对指定路径做文件系统系统调用基准测试,--iterations 默认 100 次。选型/扩容前用它对比不同磁盘(如本地 SSD vs 网络存储挂载点)的元数据操作性能。
十、用户管理命令
oCIS 没有类似 ocis user add 的本地子命令,用户管理走两条路:Graph API(reST 接口,Web 管理界面的底层)与 LDAP(内置 idm 服务暴露的只读/服务接口)。两条路操作的是同一份数据,下文实测会做交叉验证。
10.1 路线一:Graph API
第一步:获取管理员 Bearer token。 用管理员 admin 登录 Web 界面后,浏览器按 F12 打开开发者工具 → Application → Local Storage → 找到以 oc_oAuth.user: 开头的键,其 JSON 中的 access_token 字段即为 token。实测提取到的 token 长度 1248 字符。该 token 有效期只有数分钟,过期后重新登录刷新即可。
第二步:查看当前身份与用户列表。 实测输入与输出:
curl -sk https://10.89.61.3:9200/graph/v1.0/me \
-H "Authorization: Bearer $TOKEN"
{"accountEnabled":true,"displayName":"Admin","givenName":"Admin","id":"c0bd4b14-08a4-45b9-b6a9-15b2b69d93ac","identities":[{"issuer":"https://10.89.61.3:9200","issuerAssignedId":"c0bd4b14-08a4-45b9-b6a9-15b2b69d93ac"}],"mail":"admin@example.org","onPremisesSamAccountName":"admin","preferredLanguage":"en","signInActivity":{"lastSuccessfulSignInDateTime":"2026-10-22T03:18:04Z"},"surname":"Admin","userType":"Member"}
curl -sk https://10.89.61.3:9200/graph/v1.0/users \
-H "Authorization: Bearer $TOKEN"
{"value":[{"accountEnabled":true,"attributes":[],"displayName":"Admin","givenName":"Admin","id":"c0bd4b14-08a4-45b9-b6a9-15b2b69d93ac","identities":[{"issuer":"https://10.89.61.3:9200","issuerAssignedId":"c0bd4b14-08a4-45b9-b6a9-15b2b69d93ac"}],"mail":"admin@example.org","onPremisesSamAccountName":"admin","signInActivity":{"lastSuccessfulSignInDateTime":"2026-10-22T03:18:04Z"},"surname":"Admin","userType":"Member"}]}
第三步:创建用户。 实测中连续踩到三次 400 字段校验错误(这些报错原文逐字照抄,本身就有参考价值):
- 缺少登录名字段:
{"error":{"code":"invalidRequest","message":"invalid request body: no value given for required property onPremisesSamAccountName"}} - 多写了 Microsoft Graph 风格的
userName字段:{"error":{"code":"invalidRequest","message":"invalid request body: json: unknown field \"userName\""}} - 多写了
mailNotificationsEnabled字段:{"error":{"code":"invalidRequest","message":"invalid request body: json: unknown field \"mailNotificationsEnabled\""}}
💡 oCIS 的 Graph API 对请求体做严格字段校验:必填的只有
onPremisesSamAccountName(登录名)、displayName、passwordProfile.password、accountEnabled,多余的未知字段一律拒绝。照抄 Microsoft Graph 文档的 payload 在 oCIS 上是行不通的。
用最小字段集重试,实测创建成功(HTTP 201):
curl -sk -X POST https://10.89.61.3:9200/graph/v1.0/users \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"onPremisesSamAccountName":"demo","displayName":"Demo User","passwordProfile":{"password":"q1w2e3r4"},"accountEnabled":true}'
{"accountEnabled":true,"displayName":"Demo User","id":"41575d9f-bb4f-4fbd-b02e-4e6c34273f29","onPremisesSamAccountName":"demo","surname":"demo","userType":"Member"}
第四步:查询与更新。 按登录名精确查询(HTTP 200,返回体与创建响应一致):
curl -sk https://10.89.61.3:9200/graph/v1.0/users/demo \
-H "Authorization: Bearer $TOKEN"
PATCH 更新显示名(HTTP 200,响应即更新后的对象):
curl -sk -X PATCH https://10.89.61.3:9200/graph/v1.0/users/demo \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"displayName":"Demo User (updated)"}'
{"accountEnabled":true,"displayName":"Demo User (updated)","id":"41575d9f-bb4f-4fbd-b02e-4e6c34273f29","onPremisesSamAccountName":"demo","surname":"demo","userType":"Member"}
10.2 路线二:LDAP(ldapsearch)
第一步:安装 ldap-utils(Ubuntu 仓库实测装到 2.5.20):
apt-get install -y ldap-utils
Setting up ldap-utils (2.5.20+dfsg-0ubuntu0.22.04.1) ...
第二步:放行自签名证书。 idm 的 LDAPS 端口用自签名证书,ldapsearch 默认严格校验会握手失败,先写 /etc/ldap/ldap.conf:
echo "TLS_REQCERT never" >> /etc/ldap/ldap.conf
第三步:搞清真实 DN——这是 LDAP 路线最大的坑。 网上旧教程写 base DN 是 dc=ocis,dc=test、绑定账号是 uid=admin,ou=sysusers,dc=ocis,dc=test,实测在 8.1.0 上全部返回 ldap_bind: Invalid credentials (49)。完整的排障过程见第十二章 Q1,这里直接给出实测结论:
- 数据树根:
o=libregraph-idm; - 用户容器:
ou=users,o=libregraph-idm;服务账号容器:ou=sysusers,o=libregraph-idm; - 服务账号实测只有三个:
uid=libregraph(目录读取账号)、uid=idp、uid=reva——不存在uid=admin服务账号; - 口令对应关系(逐个绑定实测):
libregraph对应 ocis.yamlidm.service_user_passwords.idm_password,idp对应idp_password(也是idp.ldap.bind_password),reva对应reva_password;yaml 里的admin_password对应的是普通用户 admin(Web 登录口令)。
第四步:从 ocis.yaml 取口令(不把密钥写进命令历史)。 实测验证过的提取方式:
IDM_PW=$(awk "/^idm:/{f=1} f&&/idm_password:/{print \$2; exit}" /etc/ocis/ocis.yaml)
第五步:搜索用户目录。 实测输入与输出:
ldapsearch -H ldaps://localhost:9235 -x \
-D "uid=libregraph,ou=sysusers,o=libregraph-idm" -w "$IDM_PW" \
-b "ou=sysusers,o=libregraph-idm" "(objectClass=*)" dn
# sysusers, libregraph-idm
dn: ou=sysusers,o=libregraph-idm
# libregraph, sysusers, libregraph-idm
dn: uid=libregraph,ou=sysusers,o=libregraph-idm
# idp, sysusers, libregraph-idm
dn: uid=idp,ou=sysusers,o=libregraph-idm
# reva, sysusers, libregraph-idm
dn: uid=reva,ou=sysusers,o=libregraph-idm
# search result
search: 2
result: 0 Success
# numResponses: 5
# numEntries: 4
查普通用户(创建 demo 之前的初始状态,管理员完整条目原样照抄,可见 oCIS 的 ownCloudUser 对象类、UUID、Argon2id 口令哈希等属性):
ldapsearch -H ldaps://localhost:9235 -x \
-D "uid=libregraph,ou=sysusers,o=libregraph-idm" -w "$IDM_PW" \
-b "ou=users,o=libregraph-idm"
# users, libregraph-idm
dn: ou=users,o=libregraph-idm
objectClass: organizationalUnit
ou: users
# admin, users, libregraph-idm
dn: uid=admin,ou=users,o=libregraph-idm
cn: admin
description: An admin for this oCIS instance.
displayName: Admin
givenName: Admin
mail: admin@example.org
oCExternalIdentity: $ https://10.89.61.3:9200 $ c0bd4b14-08a4-45b9-b6a9-15b2b6
9d93ac
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: ownCloudUser
objectClass: ownCloud
objectClass: person
objectClass: top
ownCloudUUID: c0bd4b14-08a4-45b9-b6a9-15b2b69d93ac
sn: Admin
uid: admin
userPassword:: e0FSR09OMn0kYXJnb24yaWQkdj0xOSRtPTY1NTM2LHQ9MSxwPTEyJGp5S05neDl
Ydml2QVo2M2xoKzQyUUEkZDRlditlNGxTQ0dnTFRpVDRHdkgyNTMrcjNIc2RIa0F1WEFKZisxVXQw
RQ==
oCLastSignInTimestamp: 20261022031804Z
# search result
search: 2
result: 0 Success
# numResponses: 3
# numEntries: 2
第六步:交叉验证。 10.1 节通过 Graph API 创建并 PATCH 过 demo 用户后,再从 LDAP 侧查一次,实测两个入口看到的是同一份数据(displayName 已是更新后的值):
ldapsearch -H ldaps://localhost:9235 -x \
-D "uid=libregraph,ou=sysusers,o=libregraph-idm" -w "$IDM_PW" \
-b "ou=users,o=libregraph-idm" "(objectClass=person)" dn uid displayName
dn: uid=admin,ou=users,o=libregraph-idm
displayName: Admin
uid: admin
dn: uid=demo,ou=users,o=libregraph-idm
displayName: Demo User (updated)
uid: demo
⚠️ 注意:LDAP 路线在 oCIS 默认部署下只读(
ou=users下的用户数据由 graph 等服务写入,服务账号只授权读取),批量建号、改密、停启用请以 Graph API 为准;LDAP 的价值在于盘点、比对与对接外部目录工具。
十一、注意事项
- dry-run 安全阀:
trash purge-empty-dirs、revisions purge、shares clean-orphaned-grants三个破坏性命令默认--dry-run true,先看清单再显式关闭;而shares move-stuck-upload-blobs默认--dry-run false,是这一组里唯一的例外,执行前务必确认; - 停服再动存储:
decomposedfs check-treesize --repair及一切直接改 decomposedfs 目录的命令,帮助原文明确要求在 oCIS 停止状态下执行; - Graph API 字段白名单:请求体多一个字段就 400,照抄 Microsoft Graph 文档会连续碰壁,用第 10.1 节实测过的最小字段集;
- Bearer token 时效极短:实测仅数分钟即 401
token is expired,脚本化操作要么现取现用,要么改走服务账号(OCIS_SERVICE_ACCOUNT_ID/SECRET); - LDAP 是服务内部协议:
libregraph/idp/reva三个服务账号是给 oCIS 内部服务用的,不要拿去做通用集成;idm_password等密钥等于目录的读钥匙,泄露面要按生产密钥管理; - 压测默认值会打错目标:
benchmark client默认PROPFIND+admin:admin+ 单并发,对生产压测前先核对-X/-u/-j; ocis list只能本机执行:runtime 接口默认只监听localhost:9250。
十二、常见问题与排障实录
Q1:ldapsearch 一律报 Invalid credentials (49),账号密码明明是对的
现象:按旧教程用 -D "uid=admin,ou=sysusers,dc=ocis,dc=test" -w <管理口令> 绑定 ldaps://localhost:9235,无论换 admin/ldap/idm/idp/reva 哪个账号、yaml 里哪个口令,全部 ldap_bind: Invalid credentials (49),连 Web 登录正常的 uid=admin,ou=users,dc=ocis,dc=test 也一样。
排查手段:临时把 /etc/ocis/ocis.env 的 OCIS_LOG_LEVEL 改为 debug 并 systemctl restart ocis,再发起一次绑定,然后 journalctl -u ocis --since "-60 s" 看服务端的真实拒绝原因。实测抓到两种日志形态:
形态一——绑定 DN 在数据库树之外(树根不是你传的 base):
{"level":"debug","service":"idm","bind_dn":"uid=admin,ou=sysusers,o=libregraph","error":null,"op":"bind","remote_addr":"127.0.0.1:42684","time":"2026-10-22T03:26:52Z","message":"ldap bind request BindDN outside of Database tree"}
形态二——DN 已在树内,但条目不存在(账号名拼错/不存在):
{"level":"debug","service":"idm","bind_dn":"uid=admin,ou=sysusers,o=libregraph-idm","op":"bind","remote_addr":"127.0.0.1:43230","time":"2026-10-22T03:27:49Z","message":"Entry 'uid=admin,ou=sysusers,o=libregraph-idm' does not exist"}
条目存在但口令不匹配时,同样表现为 49,不再有独立提示——所以服务端日志 + 换口令对照是唯一可靠的定位方式。
结论(与实测相互印证的三个事实):数据库树根是 o=libregraph-idm(不是旧文档的 dc=ocis,dc=test,也不是字符串表里更短的 o=libregraph,少一个 -idm 后缀同样被判"树外");ou=sysusers 下只有 libregraph/idp/reva 三个服务账号;libregraph 账号用 idm_password 口令绑定后搜索成功(result: 0 Success,见 10.2 节)。排障完成后记得把日志级别改回原值。
Q2:ldapwhoami 绑定成功却报 Operations error (1)
实测 ldapwhoami -D "uid=libregraph,ou=sysusers,o=libregraph-idm" -w <正确口令> 返回 ldap_parse_result: Operations error (1),而同样的凭据用 ldapsearch 搜索一切正常。原因是 oCIS 内置的 LDAP 服务端不支持 WHOAMI 扩展操作,报错出现在绑定之后的扩展查询阶段,不代表绑定失败。判断绑定成功与否请用 ldapsearch 实际搜一次。
Q3:Graph API 创建用户报 400 invalidRequest
见 10.1 节实测:缺 onPremisesSamAccountName、多 userName、多 mailNotificationsEnabled 都会被逐字段拒绝。解决:只传 onPremisesSamAccountName / displayName / passwordProfile.password / accountEnabled 四项必填字段。
Q4:跟着旧教程配 dc=ocis,dc=test 全部失败
8.x 的目录树根已改为 o=libregraph-idm(见 Q1 实测)。旧教程对应的是早期版本,升级后 DN、服务账号命名都以本文 10.2 节的实测值为准。
Q5:Graph API 突然全部 401 token is expired
Web 登录拿到的 access_token 实测有效期只有数分钟。重新登录 Web 刷新 token,或改用服务账号机制(shares cleanup 等命令原生支持 --service-account-id/--service-account-secret)。
十三、参考链接
- oCIS 官方文档站 CLI 参考:https://docs.owncloud.com/ocis/latest/
- oCIS 源码仓库(各命令实现):https://github.com/owncloud/ocis
- 本站部署篇(systemd 安装全流程与
ocis init实录):《Ubuntu 22.04 安装 ownCloud oCIS 指南》 - 本站配置篇(OCIS_* 环境变量逐项实测):《ownCloud oCIS 配置参数详解》
- 本站认知篇(oCIS 与 Classic 双线对比):《ownCloud 介绍与选型指南》