Skip to Content
IoT 应用开发IronFlock CLI标志、输出与退出码

标志、输出与退出码

这些规则适用于每个 ironflock 命令,脚本可以依赖它们。每个命令的页面只说明该命令额外增加的内容。

命令行有以下两种形式之一:

ironflock <group> <verb> [flags] ironflock agent install -c device.flock ironflock <verb> [flags] ironflock version

命令组就是产品:agent 用于设备代理程序,appliance 用于 IronFlock Appliance,os 用于 IronFlockOS。同一个动词在每个命令组中含义相同。涉及整台机器的命令不属于任何命令组。不带动词的 ironflock 和 ironflock <group> 会输出各自的帮助。除非命令的页面另有说明,否则命令不接受位置参数;其他一切都是标志。login 和 device 是保留名称:运行它们只会得到“这是保留名称”的回答,退出码为 2。

全局标志

每个命令都接受这些标志。除 --help 外,它们都可以放在命令名称之前或之后:ironflock --json version 与 ironflock version --json 相同。

标志含义
--download-base <url>下载的基础 URL。默认值:IronFlock 云 https://instance-registry.ironflock.com/dl;对于 IronFlock Appliance 的设备,部分命令先使用 Appliance 的镜像站。参见下载基址。
--host [user@]machine通过 SSH 在该机器上运行命令,而不是在本机运行。多次给出即可用于多台机器。参见通过 SSH 管理远程机器。
--hosts <file>在文件所列的每台机器上运行命令,每行一个 [user@]machine。参见主机列表文件。
--parallel <n>--host 和 --hosts 的机器最多同时运行 n 台。默认 10,范围 1 至 100。
--json将结果作为一个 JSON 对象写到 stdout,并且不询问任何内容。
--yes以“是”回答命令的询问。它绝不会解除拒绝。
-h、--help输出命令的帮助。

名称固定的标志

同一个标志名称在每个拥有它的命令中含义相同。除 -h 外,只有 -c 和 -d 是短标志。

标志含义命令
-c、--config <file>设备的 .flock 文件agent install、agent configure、doctor、os flash、os install、os reset
-d、--drive <drive>命令写入的驱动器os flash
--disk <disk>正在运行的系统启动所用的磁盘,命令会替换它os install
--output <file>命令代替驱动器写入的文件os flash
--http-proxy、--https-proxy、--no-proxy企业代理agent install、agent configure、os install
--proxy-password-file <file>一个文件或管道,其唯一的一行是代理 URL 中用户的密码agent install、agent configure、os install

下载基址与代理

下载基址依次取自 --download-base 和环境变量 IRONFLOCK_DL_BASE,两者都没有时为 https://instance-registry.ironflock.com/dl。两者都没有给出时,agent install、doctor、os install 和 os update 会先使用设备 .flock 文件所指定的 Appliance 的下载镜像站,然后才使用云(IronFlock Appliance 的设备)。

代理先取自标志,然后取自 HTTP_PROXY、HTTPS_PROXY 和 NO_PROXY(或它们的小写形式)。agent configure 是例外:它只根据自己的标志更改设备的代理,命令的环境变量对此没有任何影响。代理 URL 形如 http://proxy.example.com:3128;https:// 和 socks5:// 同样可用,不带协议的 URL 视为 http://。代理需要登录时,在 URL 中写明用户,例如 http://[email protected]:3128,并由 --proxy-password-file 提供密码(参见机密信息)。关于位于代理之后的设备,参见位于企业代理之后。

输出与 JSON

stdout 只承载结果,别无其他。 结果要么是一段给人看的简短文本,要么在使用 --json 时恰好是一行上的一个 JSON 对象。--help 也输出到 stdout。唯一的例外是 agent logs,它的结果就是日志:使用 --json 时,它为日志的每一行写一个 JSON 对象。

stderr 承载其余一切: 进度、命令所运行工具的输出(apt、Docker 安装程序)、警告、询问和错误。

因此,重定向或命令替换只会得到结果本身;想保持安静的脚本则重定向 stderr:

# 结果以文本形式写入文件;进度和警告仍显示在终端上 ironflock status > result.txt # 结果以 JSON 形式存入 shell 变量,不含 stderr 上的消息 result=$(ironflock status --json 2>/dev/null)

JSON 中的字段名采用 snake_case。命令更改了某些内容时,结果带有字段 action,例如 "installed"、"configured" 或 "removed"。字段会随时间增加,但在一个主版本内不会被重命名或删除。读取结果的程序应忽略它不认识的字段。有多台机器时,--json 改为每台机器写一行(参见通过 SSH 管理远程机器)。

进度

耗时较长的步骤会在 stderr 上显示进度:在终端上显示为进度条,否则每完成十分之一输出一行。使用 --json 时,stdout 仍然只得到一个 JSON 对象,即结果;stderr 则以事件形式得到进度,每行一个 JSON 对象:

{"event":"progress","phase":"writing","done":104857600,"total":412345678}
字段含义
eventprogress
phasedownloading:下载镜像文件或发布版本;checking:对照目录检查其 SHA-256;preparing:根据镜像准备 os install 的写入;writing:将其写入驱动器(或 --output 的文件);verifying:通过回读验证驱动器(或文件);installing:将发布版本安装到另一个槽位(os update)
done、total字节数:downloading、checking、preparing 和 writing 时为镜像文件的字节数,verifying 时为已写入镜像的字节数。installing 时为百分比:total 为 100。

os install 在重启之前读取镜像文件两次:checking 将其 SHA-256 与已签名的目录进行比较;preparing 将镜像解包一次,以找到其 IRONFLOCKOS 分区,将设备的 .flock 文件和网络设置放入该分区,并计算写入将放到磁盘上的内容的校验和。在终端上,它们显示为 Checking 和 Preparing。

阶段开始时(done 为 0)、整数百分比每次变化时,以及阶段完成时(done 等于 total),都会产生一个事件。续传的下载会直接跳到已有的字节数。stderr 上的其他行(包括警告)是给人看的文本:程序取能解析为 JSON 对象的行,跳过其余各行。

询问与确认

会更改机器的命令先说明它要做什么,然后再询问:

  • 删除或覆盖内容的命令先说明哪些内容会消失。执行安装的命令先说明它要安装什么。agent stop 先说明停止代理程序会终止哪些内容。
  • --yes 以“是”回答命令的每个询问,并在命令提供选项时采用默认值。
  • 在终端上,询问默认选中“Yes”,因此直接按 Enter 即可继续。有三个询问默认选中“No”,因此直接按 Enter 不会擦除或删除任何内容:os flash 擦除驱动器之前、os flash 替换 --output 的文件之前,以及 agent remove。
  • os reset 要求您输入设备名称,os install 要求输入机器的主机名。输入其他任何内容(包括直接按 Enter)都视为回答“否”。
  • 询问出现之前输入的内容会被丢弃。询问要在您读完命令的说明之后才能回答。
  • Esc 表示回答“否”:命令不做任何更改,并以退出码 4 结束。在询问时按 Ctrl-C 不给出任何回答,连默认选项也不算:命令不做任何更改,并以退出码 130 结束。

询问需要 stdin 和 stderr 都连接到终端。没有终端时(管道、CI、cloud-init 脚本),命令不会等待,也不会猜测:它以退出码 4 结束,并说明可用 --yes 确认。使用 --json 时同样如此,因为它不询问任何内容。因此,脚本应同时给出 --yes 和 --json。

--yes 绝不会解除拒绝。 命令拒绝执行时(退出码 3,或某项检查失败),任何标志都不能让它继续。每个命令的页面都列出了它会拒绝的情况。唯一的例外是内部磁盘:当 --drive 指定内部磁盘时,os flash --allow-internal 会写入它。

通过 --host 运行时,如果您在终端上运行命令,询问会显示给您。同时在多台机器上运行时,没有人会被询问,因此会询问的命令只有带上 --yes 才会在那里运行(参见通过 SSH 管理远程机器)。

Root 权限

更改系统的命令需要 root。没有 root 时,它以退出码 3 结束并说明原因。它自己不会调用 sudo;只有 --host 会在另一台机器上调用。此时 os flash 会给出应输入的命令行,前面带有 sudo。

命令Root
version、completion、os images、os drives、每个 --help不需要
status、doctor不需要。没有 root 时,status 对无法读取的内容显示 unknown (needs root),doctor 将这类检查项标记为 skipped。用 sudo 运行时它们会读取这些内容。
agent install、agent configure、agent update、agent remove、agent restart、agent stop、agent start需要
agent logs需要:它只读取,但所读取的内容只有 root 可读
os flash写入驱动器时需要。使用 --output 时不需要。在 macOS 上,有权写入驱动器原始设备的用户无需 root。
os install、os update、os rollback、os reset需要
self-update需要对二进制文件所在文件夹的写权限,并且是二进制文件的所有者、属于其所属组,或者是 root。对于 /usr/local/bin/ironflock,这意味着需要 root

通过 --host 运行时,如果登录账户不是 root,需要 root 的命令会在另一台机器上通过 sudo 运行。

机密信息

任何命令都不会输出机密信息:不输出 .flock 文件中的机密,不输出 WiFi 密码,不输出代理密码,也不输出许可证密钥。这适用于 stdout、stderr、--json 和错误消息。

只要文件可以承载机密,机密就绝不作为标志的值,因为命令行会出现在 ps 和 shell 历史记录中。代理密码也不例外:

  • 标志中的代理 URL 只写用户,不写密码:http://[email protected]:3128。
  • 带密码的 URL(例如 http://user:password@proxy:3128)属于错误的命令行(退出码 2)。它会在任何操作运行之前被拒绝,带 --host 时则在发往机器之前被拒绝。错误消息不会复述它。
  • 密码来自 --proxy-password-file:一个只有一行的文件或管道(/dev/stdin)。
  • agent install 会回退使用环境中的代理变量,这些变量可以带密码:它们不在命令行上。
# 从文件读取密码 sudo ironflock agent configure --https-proxy http://[email protected]:3128 --proxy-password-file proxy-password.txt # 通过管道传入密码 sudo ironflock agent configure --proxy-password-file /dev/stdin --yes < proxy-password.txt

在由 agent install 设置的设备上,代理密码存放在只有 root 可读的位置:/etc/ironflock/proxy.env(权限 0600)。docker.service 和 ironflock-device-agent.service 的 drop-in 只写明该文件,不含任何代理设置,因此 systemctl show 只会让每个用户看到该文件的名称,看不到其中的内容。

通过 --host 运行时,标志中指定的 .flock 文件、WiFi 密码文件或代理密码文件会经由 SSH 连接发送到另一台机器,绝不会出现在命令行上(参见通过 SSH 管理远程机器)。含有登录信息的下载基址会在连接任何机器之前以退出码 2 结束。

退出码

代码类别含义
0完成
1failed命令已开始,但无法完成
2usage命令行有误:未知的命令或标志、缺少标志、保留名称。未改动任何内容。
3precondition机器不处于命令所需的状态:不是 root、未安装代理程序、已经安装了代理程序、命令不支持的系统。未改动任何内容。
4declined询问被回答为“否”,或者无法询问且未给出 --yes
130interrupted在命令完成之前被中断(Ctrl-C);带 --host 时,也包括另一台机器上因挂断、中断或终止信号而结束的命令
255ssh--host 的 SSH 连接失败:未能连接到机器,或连接中断

错误是 stderr 上的一行:Error: 后跟消息。用法错误之后还有一行,指出应阅读哪个 --help。使用 --json 时,错误就是结果:stdout 得到一个错误对象,stderr 不输出错误行。kind 是表中的类别之一。

{"error":{"kind":"precondition","message":"the agent is not installed on this machine"}}

有两个命令会写出结果,但仍以退出码 1 结束。agent update 在代理程序停留在原版本时如此:结果说明原因,stderr 得到 Error: 行。doctor 在某项检查失败时如此:结果说明是哪一项,之后没有错误行。使用 --json 时,这两个命令此时都不写错误对象:stdout 中是结果。

带 --help 时,未知命令不算错误:ironflock os nosuch --help 输出 ironflock os 的帮助,退出码为 0。在多台机器上运行时,命令以各机器中最差的退出码结束(参见通过 SSH 管理远程机器)。

中断

Ctrl-C、SIGTERM 和 SIGHUP(终端或 SSH 会话消失时)会像结束任何程序一样立即结束大多数命令,不输出错误行;shell 看到的是 130(SIGTERM 之后为 143,SIGHUP 之后为 129)。有些步骤会处理这些信号:

  • os flash 在下载、写入或回读镜像时,以及 os update 在下载和检查更新包时,会在下一个数据块处停止。它们以 interrupted 类别的错误说明留下了什么,并以 130 结束;此时 os update 不会安装任何内容。os flash 一旦回读完最后一个数据块,就会完成收尾步骤并以 0 结束。再按一次 Ctrl-C 会立即结束进程;使用 --output 时,可能会留下 .part 文件。
  • agent logs --follow 持续跟踪日志,直到收到这类信号,然后以 0 结束。
  • agent update 以 130 停止跟踪更新;代理程序会自行继续更新。
  • os reset 在写入其请求时,会撤回该请求并以 130 结束,设备不会重启。
  • agent configure 一旦开始更改机器,就不再因终端或 SSH 会话丢失而停止。Ctrl-C 和 SIGTERM 仍会立即结束它。
  • os install 在其询问之前和之后的行为不同;参见 ironflock os install。

在脚本中使用退出码

脚本给出 --yes,让命令不会停在询问处;给出 --json,以得到可读取的结果;然后检查退出码:

#!/bin/sh # 让代理程序自行更新;保留 JSON 结果,丢弃 stderr 上的进度。 result=$(sudo ironflock agent update --yes --json 2>/dev/null) code=$? case $code in 0) echo "agent is current: $result" ;; 1) echo "agent update failed: $result" ;; 3) echo "agent update refused on this machine: $result" ;; *) echo "agent update ended with exit code $code: $result" ;; esac

退出码为 0 时,$result 中是结果,其 outcome 为 updated 或 current。退出码为 1 时,其中要么是结果(其 outcome 和 reason 说明代理程序为何停留在原版本),要么是错误对象。退出码为 3 时,其中是错误对象。

Last updated on