跳到主要内容

opsctl exec

任意资产上执行命令 —— SSH 服务器、数据库、Redis、MongoDB、etcd、Kafka、Kubernetes、对象存储,统统走这一个命令。

信息

早期版本有独立的 opsctl sqlopsctl redisopsctl mongo 三个子命令,现已移除。改用 opsctl exec,命令内容按资产类型的语法书写(见下文)。

语法

opsctl [global-flags] exec <asset> [--type <type>] [--] <command>

参数

参数说明
asset资产名称或数字 ID。可使用 group/name 格式消歧。
command要执行的命令,按该资产类型的语法书写。使用 -- 将命令与 opsctl 参数分隔,-- 之后的所有内容会被拼接为一个完整的命令字符串。

参数选项

选项说明
--type <type>可选的断言:资产类型不符时立即报错退出。它决定派发方式 —— 派发永远由资产的真实类型决定。可填的值见--type 可填哪些值

--type 可填哪些值

可填三类值:

类别取值断言什么
规范资产类型sshserialdatabaseredismongodbetcdkafkak8soss资产类型
协议别名exec → ssh,sql / db → database,mongo → mongodb,kubernetes / kube → k8s资产类型
数据库驱动名mysqlpostgresql / postgresmssql / sqlserversqlite / sqlite3资产类型外加驱动

驱动名的断言是刻意更严的。--type mysql 要求资产是 database 且驱动确实是 MySQL,打在 PostgreSQL 资产上会直接失败:

$ opsctl exec analytics --type mysql -- "SELECT 1"
Error: asset "analytics" is a database with driver=postgresql, but you passed type=mysql — call help(asset="analytics") for its command syntax

如果 mysql 只是 database 的普通同义词,这条命令就会照跑不误 —— 断言也就白设了。日常优先写规范类型,只有当方言真的影响这条命令时才用驱动名。

派发方式

命令怎么跑,由资产自身的类型决定:

  • ssh 资产走流式通道 —— 转发 stdin、实时输出 stdout/stderr、远端退出码原样作为 opsctl 的退出码。
  • 其余类型databaseredismongodbetcdkafkak8soss 等)走统一 exec 处理器,返回捕获后的输出,通常是 JSON。

各类型的命令语法

执行 opsctl help <asset>(或 opsctl help <type>)可查看该类型权威的命令语法、配置字段和注意事项。它是只读的,从不触发审批。

opsctl help prod-db      # 传资产
opsctl help kafka # 传类型名,即使还没有该类型的资产也能查

速查表:

资产类型命令语法示例
sshShell 命令原样传入opsctl exec web-01 -- uptime
databaseSQL 原样传入opsctl exec prod-db -- "SELECT id, name FROM users LIMIT 10"
redisRedis 命令原样传入opsctl exec cache -- "HGETALL user:1"
mongodb<operation> [collection] [--db=<db>] [--query=<json>]opsctl exec mongo-db -- find users --query='{"filter":{"active":true},"limit":10}'
etcd<op> [key] [value] [--flags](etcdctl 子集)opsctl exec etcd-01 -- get /app/ --prefix
kafka<family> <verb> [target] [--flags]opsctl exec kafka-01 -- topic describe orders
k8skubectl 命令,带不带开头的 kubectl 都行opsctl exec prod-cluster -- get pods -A
oss<family> <verb> [target] [--flags]opsctl exec s3-prod -- object list backups/2026/

几个实际容易踩的点:

  • Redis: 绝对不要发 SELECT。连接是池化的,SELECT 要么不生效,要么破坏其他调用方的库选择。
  • MongoDB: --db 属于命令内容,不是 opsctl 的参数;不写则用资产配置的默认库。--query 一律用单引号包起来。
  • 数据库 / Redis: CLI 没有单次调用切库的选项,一律使用资产配置的默认数据库(或 Redis DB 编号)。
  • 非 SSH 的命令只做分词,经过 shell 执行:$|>& 会直接报错而不是展开。含这些字符的值请用单引号包住。

管道支持(仅 ssh 资产)

当标准输入不是终端(即数据通过管道传入)时,输入数据会被转发到远程命令的 stdin。远程命令的 stdout 和 stderr 会直接写入本地的 stdout 和 stderr,从而支持 Unix 管道链式调用。

远程命令的退出码会作为 opsctl 的退出码返回。

审批

此命令按资产自身类型的策略检查 —— database 资产走 SQL 策略,redis 资产走 Redis 策略,以此类推:

  • 匹配资产白名单的命令无需审批即可执行
  • 匹配黑名单的命令会被立即拒绝
  • 未命中规则时,交互调用会在当前终端提问;非交互调用可在桌面可达时使用桌面审批
  • 两种审批路径都不可用时,以退出码 3 输出 NEEDS AUTHORIZATION 和可复制的 opsctl policy allow;真人执行授权后再重试

示例

# 按名称、ID 或 分组/名称 指定资产
opsctl exec web-server -- uptime
opsctl exec 1 -- ls -la /var/log
opsctl exec production/web-01 -- cat /etc/hosts

# 先断言资产类型,类型不对就立即失败
opsctl exec cache --type redis -- "GET session:abc123"

# 查询数据库
opsctl exec prod-db -- "SELECT COUNT(*) FROM users"

# MongoDB、etcd、Kafka、Kubernetes、对象存储
opsctl exec mongo-db -- countDocuments users --db=app
opsctl exec etcd-01 -- put /app/config '{"debug":true}'
opsctl exec kafka-01 -- topic list
opsctl exec prod-cluster -- logs deploy/api --tail 100
opsctl exec s3-prod -- object stat backups/2026/db.sql.gz

# 通过管道向远程命令传入数据(仅 ssh)
echo "hello" | opsctl exec web-server -- cat

# 与本地命令链式调用,并利用透传的退出码
opsctl exec web-server -- cat /etc/nginx/nginx.conf | grep upstream
opsctl exec web-server -- test -f /opt/app/config.yml && echo "exists"

# 真人可先在交互终端写入永久规则
opsctl policy allow web-01 -- 'systemctl restart *'