Apache Fluo 2.0.0 常用 CLI 命令与工具详解

完整覆盖 Apache Fluo 2.0.0 全部 CLI 子命令与 lib/fetch.sh 依赖脚本:init/remove/scan/config/classpath 等逐个给出参数说明与实测回显,含 --raw 底层键值、init -u 配置更新、Java 客户端事务读写演示与配套运维工具链速查

Apache FluoFluoApache运维大数据2026/10/14

Apache Fluo 2.0.0 常用 CLI 命令与工具详解

目标:完整覆盖 Apache Fluo 2.0.0 命令行工具 bin/fluo 的全部子命令与依赖脚本 lib/fetch.sh,每个命令给出参数说明与实测回显(数据操作命令基于演示应用 myapp2 的 3 行演示数据),并整理 Fluo 日常运维涉及的配套工具(jps、journalctl、accumulo shell、zkCli.sh、hdfs)。环境为 Ubuntu 22.04.5 + Fluo 2.0.0 + Accumulo 2.1.0 + Hadoop 3.3.6 + ZooKeeper 3.8.4(安装见《Ubuntu 22.04 安装 Apache Fluo 2.0.0 指南》,配置见《Apache Fluo 2.0.0 配置参数详解》)。

一、CLI 总览

Fluo 的全部子命令由单一入口脚本 bin/fluo 提供,无参数执行可查看用法:

fluo

实测输出:

Usage: fluo <command> (<argument> ...)

Possible commands:

  init -a <app> -p <appProps>   Initializes Fluo application for <app> using <appProps>. Run with -h to see additional args.
  remove -a <app>               Removes Fluo application for <app>
  classpath                     Prints the classpath setup in fluo-env.sh
  config -a <app>               Prints application configuration stored in Zookeeper for <app>
  get-jars -a <app> -d <dir>    Copies <app> jars from DFS to local <dir>
  list                          Lists all Fluo applications in Fluo instance
  scan -a <app>                 Prints snapshot of data in Fluo <app>
  status -a <app>               Prints status of Fluo application for <app>
  oracle -a <app>               Starts Fluo Oracle process for <app>
  worker -a <app>               Starts Fluo Worker process for <app>
  version                       Prints the version of Fluo
  wait -a <app>                 Waits until all notifications are processed for <app>
  exec <app> <class> {<arg>}    Executes <class> with <args> using classpath for <app>

按用途分组:

分组命令用途
应用生命周期init、remove、status、list初始化/删除应用、查看状态与清单
数据操作scan、wait、exec快照扫描、等待通知处理、执行应用内类
配置与依赖config、classpath、get-jars、version查看固化配置、classpath、取回 jar
服务进程oracle、worker前台启动服务进程
依赖脚本lib/fetch.sh补齐 Accumulo/Hadoop/ZK 依赖

💡 说明:各子命令均支持 -h 查看专属参数(如 fluo init -h、fluo scan -a myapp2 -h)。

二、应用生命周期命令

2.1 fluo init(初始化应用)

语法:fluo init -a <app> -p <appProps>,应用属性经 -p 指定的文件固化到 ZooKeeper,同时在 HDFS 建目录、在 Accumulo 建表:

fluo init -a myapp2 -p /opt/fluo-2.0.0/conf/myapp.properties

实测输出:

Initializing Fluo 'myapp2' application using /opt/fluo-2.0.0/conf/myapp.properties
Initialization is complete.

-h 显示的完整选项(本文环境实测摘录,限于篇幅省略末尾 -a/-p 参数说明):

Usage: fluo init [options]
  Options:
    --clearTable
      Skips prompt and clears Accumulo table
      Default: false
    --clearZookeeper
      Skips prompt and clears Zookeeper
      Default: false
    -f, --force
      Skip all prompts and clears Zookeeper and Accumulo table.  Equivalent to
      setting both --clearTable --clearZookeeper
      Default: false
    -h, -help, --help
      Prints help
    --retrieveProperty
      Gets specified property without initializing
    -u, --update
      Update Fluo configuration in Zookeeper
      Default: false

两个高频场景:

更新已固化配置(-u)——修改 myapp.properties 后无需删除应用,先停服务再更新:

fluo init -u -a myapp2 -p /opt/fluo-2.0.0/conf/myapp.properties

实测输出(应用已停止时):

Updating configuration for the Fluo 'myapp2' application in Zookeeper using /opt/fluo-2.0.0/conf/myapp.properties
Update is complete.

应用运行中执行 -u 会报错中止、不会破坏状态(实测):

Updating configuration for the Fluo 'myapp2' application in Zookeeper using /opt/fluo-2.0.0/conf/myapp.properties
Exception in thread "main" org.apache.fluo.api.exceptions.FluoException: Error - The Fluo 'myapp2' application is already running and must be stopped before updating shared configuration.  Aborted update.
        at org.apache.fluo.core.client.FluoAdminImpl.updateSharedConfig(FluoAdminImpl.java:321)
        at org.apache.fluo.command.FluoInit.execute(FluoInit.java:133)
        at org.apache.fluo.command.FluoProgram.runFluoCommand(FluoProgram.java:69)
        at org.apache.fluo.command.FluoProgram.main(FluoProgram.java:33)

强制重置(-f)——等价于同时给 --clearTable --clearZookeeper,跳过全部确认提示清空 Accumulo 表与 ZK 配置后重新初始化,适用于丢弃数据的重建场景。

2.2 fluo remove(删除应用)

删除前必须停止 Oracle/Worker,并等待约 30–40 秒(ZK 应用状态有会话超时延迟)。remove 自动清理 ZooKeeper 应用节点、Accumulo 表与 HDFS 应用目录:

fluo remove -a myapp2

实测输出:

Removing Fluo 'myapp2
Remove is complete.

⚠️ 注意:应用未停止或 ZK 状态未更新时执行 remove 会报应用仍在运行;Removing Fluo 'myapp2 行末尾没有闭合引号是命令真实输出原样,非笔误。

2.3 fluo status(应用状态)

fluo status -a myapp2

实测输出:

RUNNING

状态值用于脚本判断(服务停止后 ZK 状态约 30 秒才变为 STOPPED,脚本化停止流程要预留等待)。

2.4 fluo list(实例应用清单)

fluo list

实测输出:

Fluo instance (localhost:2181/fluo) contains 1 application(s)

Application     Status     # Workers     # Oracles
-----------     ------     ---------     ---------
myapp2          RUNNING        1             1

首行同时回显了实例连接串(来自 fluo-conn.properties),可快速核对 chroot 是否正确。

三、数据操作命令

3.1 fluo scan(快照扫描)

对应用做一致性快照扫描,是排障最常用的命令。基础用法:

fluo scan -a myapp2

实测输出(演示数据 3 行):

user:0001 info age      30
user:0001 info name     Alice
user:0002 info name     Bob

输出格式为「行键 列族 列限定符 值」。常用选项(-h 实测):

选项作用说明
-p <prefix>按行键前缀过滤
-r <row>精确匹配某一行
-s <start> / -e <end>起始/结束行(含端点)范围扫描
-c <cols>列裁剪格式 列族[:列限定符]{,列族[:列限定符]}
--raw展示 Accumulo 底层键值按 Fluo 内部结构解读(见下)
--json以 JSON 行输出便于程序化处理
--ntfy扫描活动通知观察者排障用
-esc非 ASCII 字节十六进制编码
-o <k>=<v>临时覆盖属性

实测示例——列裁剪(只看 info:age):

fluo scan -a myapp2 -c "info:age"

实测输出:

user:0001 info age      30

实测示例——精确行与前缀过滤:

fluo scan -a myapp2 -r user:0002

实测输出:

user:0002 info name     Bob
fluo scan -a myapp2 -p user:0001 -c "info:name"

实测输出:

user:0001 info name     Alice

实测示例——底层键值(--raw,可看到 Fluo 事务的 WRITE/DATA/TX_DONE 结构):

fluo scan -a myapp2 --raw | head -8

实测输出:

user:0001 info:age [] 4-WRITE   3
user:0001 info:age [] 3-DATA    30
user:0001 info:name [] 4-TX_DONE
user:0001 info:name [] 4-WRITE  3 PRIMARY
user:0001 info:name [] 3-DATA   Alice
user:0002 info:name [] 4-WRITE  3
user:0002 info:name [] 3-DATA   Bob

3-DATA 是数据单元、4-WRITE 是提交指针(数字为事务开始时间戳,PRIMARY 标记主提交列)、4-TX_DONE 是事务完成标记——这些正是 Fluo 快照隔离的实现载体,排障时可据此判断事务残留。

实测示例——JSON 输出:

fluo scan -a myapp2 --json | head -4

实测输出:

{"row":"user:0001","family":"info","qualifier":"age","visibility":"","value":"30"}
{"row":"user:0001","family":"info","qualifier":"name","visibility":"","value":"Alice"}
{"row":"user:0002","family":"info","qualifier":"name","visibility":"","value":"Bob"}

3.2 fluo wait(等待通知处理完成)

阻塞至应用内所有活动通知处理完毕,常用于观察者流水线验证与脚本收尾:

fluo wait -a myapp2

实测输出:

(无输出,退出码 0)

💡 说明:本文演示应用未配置观察者,无通知积压,wait 立即返回;配置观察者后,wait 会等到通知全部消化。

3.3 fluo exec(执行应用内类)

用应用的 classpath 执行类(类需已通过 fluo.accumulo.jars 上传到 DFS):

fluo exec myapp2 FluoWriter

实测输出(类未上传到 DFS 时):

fluo exec failed - Class FluoWriter not found

本地开发调试可绕过 DFS 上传,直接用 fluo classpath 拼接运行(见 3.4)。

3.4 事务读写客户端(Java API + classpath)

演示程序 /opt/demo/FluoWriter.java(事务写入 3 行):

import org.apache.fluo.api.client.FluoClient;
import org.apache.fluo.api.client.FluoFactory;
import org.apache.fluo.api.client.Transaction;
import org.apache.fluo.api.config.FluoConfiguration;
import org.apache.fluo.api.data.Column;

public class FluoWriter {
  public static void main(String[] args) throws Exception {
    FluoConfiguration config = new FluoConfiguration();
    config.setApplicationName("myapp2");
    config.setInstanceZookeepers("localhost:2181/fluo");
    config.setAccumuloInstance("accumulo1");
    config.setAccumuloZookeepers("localhost:2181");
    config.setAccumuloUser("root");
    config.setAccumuloPassword("q1w2e3r4");
    config.setAccumuloTable("myapp2");
    try (FluoClient client = FluoFactory.newClient(config)) {
      try (Transaction tx = client.newTransaction()) {
        tx.set("user:0001", new Column("info","name"), "Alice");
        tx.set("user:0001", new Column("info","age"), "30");
        tx.set("user:0002", new Column("info","name"), "Bob");
        tx.commit();
      }
    }
    System.out.println("3 rows committed");
  }
}

编译(fluo-api jar 在发行包 lib/ 中):

cd /opt/demo
javac -cp "/opt/fluo-2.0.0/lib/*" FluoWriter.java

运行(fluo classpath 输出 + 演示类目录):

java -cp "$(/opt/fluo-2.0.0/bin/fluo classpath):/opt/demo" FluoWriter

实测输出:

3 rows committed

⚠️ 注意:客户端 setInstanceZookeepers() 必须带 chroot /fluo,与 fluo-conn.properties 一致;事务内 tx.set() 在 tx.commit() 成功前对外不可见。

四、配置与依赖工具

4.1 fluo config(查看固化配置)

fluo config -a myapp2

实测输出:

fluo.dfs.root = hdfs://localhost:9000/fluo
fluo.accumulo.password = q1w2e3r4
fluo.accumulo.table = myapp2
fluo.accumulo.instance = accumulo1
fluo.accumulo.user = root

输出即 ZooKeeper 中固化的应用属性(不是本地文件内容),修改本地文件后以此命令验证是否已更新。

4.2 fluo classpath(查看 classpath 装配)

fluo classpath

实测输出:

/opt/fluo-2.0.0/lib/*:/opt/fluo-2.0.0/lib/log4j/*:/opt/fluo-2.0.0/lib/ahz/*

分号/冒号连接的三个目录即 fluo-env.sh 中 setupClasspathFromLib 装配的结果;客户端程序把它与自有类目录拼接即可运行。

4.3 fluo get-jars(取回应用 jar)

把应用上传到 DFS 的 jar 拷回本地目录:

rm -rf /tmp/getjars && fluo get-jars -a myapp2 -d /tmp/getjars

实测输出(未通过 fluo.accumulo.jars 上传过自定义 jar 时):

(无输出,退出码 0,目标目录不创建)

配置 fluo.accumulo.jars 并重新初始化后,该命令才有 jar 可取。

4.4 lib/fetch.sh(依赖下载脚本)

Fluo 发行包不含 Accumulo/Hadoop/ZK 依赖,需两步补齐(需 Maven):

/opt/fluo-2.0.0/lib/fetch.sh extra

实测输出(依赖已在本地 Maven 缓存时只回显 SUCCESS):

SUCCESS: Dependency exists - /opt/fluo-2.0.0/lib/./log4j/log4j-core-2.19.0.jar
SUCCESS: Dependency exists - /opt/fluo-2.0.0/lib/./log4j/log4j-slf4j2-impl-2.19.0.jar
Done!

NOTE - The dependencies downloaded have been tested with some versions of Hadoop, Zookeeper, and Accumulo.
There is no guarantee they will work with all versions. Fluo chose to defer dependency resolution to as
late as possible in order to make it easier to resolve dependency conflicts.  If you run into a dependency
conflict in your environment, please consider bringing it up on the Fluo dev list.
/opt/fluo-2.0.0/lib/fetch.sh ahz -Daccumulo.version=2.1.0 -Dhadoop.version=3.3.6 -Dzookeeper.version=3.8.4

实测输出节选(首次执行为 Maven 真实下载过程,此处为缓存命中的快速回显):

[INFO] Scanning for projects...
[INFO] Copying hadoop-client-api-3.3.6.jar to /opt/fluo-2.0.0/lib/ahz/target/../hadoop-client-api-3.3.6.jar
[INFO] Copying netty-transport-native-epoll-4.1.105.Final.jar to /opt/fluo-2.0.0/lib/ahz/target/../netty-transport-native-epoll-4.1.105.Final.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.371 s

4.5 fluo version(版本号)

fluo version

实测输出:

2.0.0

五、服务进程命令

fluo oracle -a <app> 与 fluo worker -a <app> 前台启动服务进程。生产推荐 systemd 托管(单元文件与参数详解见安装指南第九章、配置详解第五章),前台方式主要用于调试——直接观察控制台输出:

方式命令适用场景
systemd 托管systemctl start fluo-oracle、systemctl start fluo-worker生产/长期运行(自启、故障拉起、日志入 journal)
前台运行fluo oracle -a myapp2、fluo worker -a myapp2调试观察实时输出

systemd 托管下的日常检查:

systemctl is-active fluo-oracle

实测输出:

active
systemctl is-active fluo-worker

实测输出:

active

进程级验证(两个 FluoProgram 进程即 Oracle 与 Worker,可核对堆参数与连接配置注入):

jps -lv | grep FluoProgram

实测输出:

28964 org.apache.fluo.command.FluoProgram -Xms256m -Xmx256m -Dfluo.conn.props=/opt/fluo-2.0.0/conf/fluo-conn.properties
28952 org.apache.fluo.command.FluoProgram -Xms256m -Xmx256m -Dfluo.conn.props=/opt/fluo-2.0.0/conf/fluo-conn.properties

Oracle 运行日志(含选主与监听端口,端口为动态分配):

journalctl -u fluo-oracle --no-pager -o cat | grep -E "Listening|Assumed" | head -2

实测输出:

2026-10-14T12:16:18,124 [oracle.OracleServer] INFO : Listening 0.0.0.0/0.0.0.0:39683
2026-10-14T12:16:18,142 [oracle.OracleServer] INFO : Assumed leadership node1.fluo.example:39683

六、配套工具链速查

Fluo 运行在 Hadoop/ZK/Accumulo 之上,排障时经常需要下面的配套命令(均为本文环境实测):

工具命令示例用途
jpsjps -lv确认各 JVM 进程与堆参数注入
journalctljournalctl -u fluo-oracle --no-pager -o cat查看 systemd 托管的 Oracle/Worker 日志
accumulo shellaccumulo shell -e "tables -np"非交互执行 Accumulo 命令(列系统表与应用表)
zkCli.shzkCli.sh -server localhost ls /fluo检查 Fluo 在 ZK 的应用节点
hdfshdfs dfs -ls /检查 /accumulo、/fluo 目录
zkServer.shzkServer.sh statusZK 服务状态

关键实测回显:

accumulo shell -e "tables -np"

实测输出(myapp2 表存在即应用数据链路完好):

Loading configuration from /opt/accumulo-2.1.0/conf/accumulo-client.properties
accumulo.metadata
accumulo.replication
accumulo.root
myapp2
zkServer.sh status

实测输出:

ZooKeeper JMX enabled by default
Using config: /opt/apache-zookeeper-3.8.4-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: standalone

💡 说明:zkCli.sh 支持把多条命令作为参数一次执行(如 zkCli.sh -server localhost addauth digest <user>:<pass> deleteall <path>),适合脚本化清理;交互式管道输入(printf | zkCli.sh)不会被执行。

七、常见问题

Q1:fluo exec 报 Class <类名> not found? fluo exec 只查找已上传到 DFS 的应用 jar(fluo.accumulo.jars 配置项)。本地调试用 java -cp "$(/opt/fluo-2.0.0/bin/fluo classpath):<类目录>" <类名> 代替(实测见 3.3、3.4)。

Q2:fluo scan 报 NoClassDefFoundError: org/apache/log4j/Logger? classpath 混用两种装配方式导致日志实现冲突。fluo-env.sh 末尾只保留一个装配调用(本文为 setupClasspathFromLib)。

Q3:停止服务后立刻 fluo remove/fluo init -u 报应用仍在运行? ZK 应用状态有约 30 秒会话超时延迟。等待 30–40 秒或用 fluo status -a myapp2 确认后再操作。

Q4:fluo 任意命令报 NoClassDefFoundError(curator 等)? 依赖未补齐。按 4.4 执行两次 lib/fetch.sh,并确认 ls /opt/fluo-2.0.0/lib/ahz | wc -l 为 49。

Q5:systemctl stop 后 unit 状态为 failed? JVM SIGTERM 退出码 143 未被声明为成功。单元文件加 SuccessExitStatus=143 后 systemctl daemon-reload。

八、参考链接