フラグ、出力、終了コード
これらのルールはすべての ironflock コマンドに当てはまり、スクリプトはこれを前提にできます。各コマンドのページには、そのコマンドが追加するものだけを記載しています。
コマンドラインの形は、次の 2 つのどちらかです:
ironflock <group> <verb> [flags] ironflock agent install -c device.flock
ironflock <verb> [flags] ironflock versionグループは製品を表します。デバイスエージェントは agent、IronFlock アプライアンスは appliance、IronFlockOS は os です。動詞はどのグループでも同じ意味です。マシン全体に関わるコマンドにはグループがありません。動詞を付けない 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 アプライアンスのデバイスでは、一部のコマンドがアプライアンスのミラーを先に使います。ダウンロードベース を参照してください。 |
--host [user@]machine | コマンドを、ここではなく SSH 経由でそのマシン上で実行します。複数のマシンには、複数回指定します。SSH 経由のリモートマシン を参照してください。 |
--hosts <file> | ファイルに記載された各マシンでコマンドを実行します。1 行に 1 つの [user@]machine を記載します。ホスト一覧ファイル を参照してください。 |
--parallel <n> | --host と --hosts のマシンのうち、同時に実行するのは最大 n 台です。既定値は 10、範囲は 1〜100 です。 |
--json | 結果を 1 つの 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 に記載したユーザーのパスワードを 1 行で含むファイルまたはパイプ | 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 ファイルが指定するアプライアンスのダウンロードミラーを使います(IronFlock アプライアンスのデバイス)。
プロキシは、フラグ、次に HTTP_PROXY、HTTPS_PROXY、NO_PROXY(またはその小文字の形)から取得されます。例外は agent configure です。このコマンドはフラグだけでデバイスのプロキシを変更し、コマンドの環境はそこでは何も変えません。プロキシ URL は http://proxy.example.com:3128 のような形です。https:// と socks5:// も使え、スキームのない URL は http:// として扱われます。プロキシにログインが必要な場合は、http://[email protected]:3128 のように URL でユーザーを指定し、パスワードは --proxy-password-file で渡します(シークレット を参照)。プロキシの背後にあるデバイスについては、企業プロキシの背後で を参照してください。
出力と JSON
stdout には結果だけが出力されます。 結果は、人が読む短いテキストか、--json を付けた場合は 1 行の JSON オブジェクトちょうど 1 つです。--help も stdout に出力されます。唯一の例外は agent logs で、その結果はログです。--json を付けると、ログの 1 行ごとに 1 つの JSON オブジェクトを出力します。
それ以外はすべて stderr に出力されます: 進捗、コマンドが実行するツール(apt、Docker のインストーラー)の出力、警告、質問、エラーです。
そのため、リダイレクトやコマンド置換では結果だけが得られます。メッセージを表示させたくないスクリプトは、stderr をリダイレクトします:
# 結果をテキストでファイルに保存する。進捗と警告は引き続き端末に表示される
ironflock status > result.txt
# 結果を JSON でシェル変数に格納する。stderr のメッセージは表示しない
result=$(ironflock status --json 2>/dev/null)JSON のフィールド名は snake_case です。コマンドが何かを変更した場合、結果にはフィールド action があります(例:"installed"、"configured"、"removed")。フィールドは今後追加されることがありますが、メジャーバージョン内で名前が変わったり削除されたりすることはありません。結果を読み取るプログラムは、知らないフィールドを無視してください。複数のマシンでは、--json は代わりにマシンごとに 1 行を出力します(SSH 経由のリモートマシン を参照)。
進捗
時間のかかる手順は、進み具合を stderr に表示します。端末ではバーで、それ以外では 10 分の 1 進むごとに 1 行で表示します。--json を付けても、stdout には結果である JSON オブジェクトがちょうど 1 つだけ出力されます。stderr には進捗がイベントとして、1 行に 1 つの JSON オブジェクトで出力されます:
{"event":"progress","phase":"writing","done":104857600,"total":412345678}| フィールド | 意味 |
|---|---|
event | progress |
phase | downloading:イメージファイルまたはリリースのダウンロード。checking:その SHA-256 をカタログと照合。preparing:イメージから os install の書き込みを準備。writing:ドライブ(または --output のファイル)への書き込み。verifying:ドライブ(またはファイル)を読み戻しての検証。installing:リリースをもう一方のスロットにインストール(os update) |
done, total | バイト数。downloading、checking、preparing、writing ではイメージファイルの、verifying では書き込んだイメージのバイト数です。installing ではパーセントで、total は 100 です。 |
os install は、再起動の前にイメージファイルを 2 回読み取ります。checking はその SHA-256 を署名済みカタログと照合します。preparing はイメージを 1 回展開して IRONFLOCKOS パーティションを見つけ、そこにデバイスの .flock ファイルとネットワーク設定を入れ、書き込みがディスクに置くもののチェックサムを計算します。端末では、それぞれ Checking、Preparing と表示されます。
イベントは、フェーズの開始時(done は 0)、パーセントの整数値が変わるたび、フェーズの完了時(done が total と等しい)に出力されます。再開したダウンロードは、すでにあるバイト数まで一気に進みます。stderr のほかの行は、警告も含めて人が読むためのテキストです。プログラムは、JSON オブジェクトとして解析できる行を取り出し、残りを読み飛ばします。
質問と確認
マシンを変更するコマンドは、まず何をするかを示し、それから質問します:
- 何かを削除または上書きするコマンドは、まず何がなくなるかを示します。インストールするコマンドは、まず何をインストールするかを示します。
agent stopは、エージェントを停止すると何が止まるかを最初に示します。 --yesは、コマンドのすべての質問に「はい」と答え、コマンドが選択肢を示す場合は既定値を選びます。- 端末では、質問は「Yes」があらかじめ選択されているため、Enter だけで先に進みます。3 つの質問では「No」があらかじめ選択されているため、Enter だけでは何も消去も削除もされません。ドライブを消去する前の
os flash、--outputのファイルを置き換える前のos flash、そして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 では、ドライブの raw デバイスに書き込めるユーザーには 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 やシェルの履歴に表示されるためです。プロキシのパスワードも例外ではありません:
- フラグで指定するプロキシ URL には、パスワードを含めずにユーザーを記載します:
http://[email protected]:3128。 http://user:password@proxy:3128のようにパスワードを含む URL は、コマンドラインの誤り(終了コード 2)です。何かが実行される前に、--hostの場合はマシンに送られる前に拒否されます。エラーメッセージには、その URL は繰り返されません。- パスワードは
--proxy-password-fileから取得します。1 行のファイル、またはパイプ(/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.txtagent install がセットアップしたデバイスでは、プロキシのパスワードは root だけが読める場所、/etc/ironflock/proxy.env(モード 0600)にあります。docker.service と ironflock-device-agent.service のドロップインはこのファイルの名前を記載するだけで、プロキシの設定は含みません。そのため systemctl show からすべてのユーザーにわかるのはファイルの名前だけで、その内容はわかりません。
--host では、フラグで指定した .flock ファイル、WiFi パスフレーズのファイル、プロキシのパスワードのファイルは、SSH 接続を通じて別のマシンに送られ、コマンドラインに載ることはありません(SSH 経由のリモートマシン を参照)。ログイン情報を含むダウンロードベースを指定すると、どのマシンにも接続する前に終了コード 2 で終了します。
終了コード
| コード | 種類 | 意味 |
|---|---|---|
| 0 | 完了 | |
| 1 | failed | コマンドは開始したが、完了できなかった |
| 2 | usage | コマンドラインが誤っている:不明なコマンドやフラグ、指定されていない必須のフラグ、予約された名前。何も変更されていません。 |
| 3 | precondition | マシンが、コマンドに必要な状態にない:root でない、エージェントがインストールされていない、エージェントがすでにインストールされている、コマンドが動作しないシステムである。何も変更されていません。 |
| 4 | declined | 質問に「いいえ」と答えた、または質問できず、--yes も指定されていなかった |
| 130 | interrupted | コマンドの完了前に中断された(Ctrl-C)。--host では、別のマシン上のコマンドがハングアップ、割り込み、終了シグナルで終了した場合も含む |
| 255 | ssh | --host の SSH 接続に失敗した:マシンに到達できなかった、または接続が切れた |
エラーは stderr の 1 行で、Error: の後にメッセージが続きます。使い方の誤りの場合は、その後に、読むべき --help を示す行が続きます。--json では、エラーが結果になります。stdout にはエラーオブジェクトが出力され、stderr にはエラーの行は出力されません。kind は表にある種類のいずれかです。
{"error":{"kind":"precondition","message":"the agent is not installed on this machine"}}2 つのコマンドは、結果を出力したうえで終了コード 1 で終了します。agent update は、エージェントが現在のバージョンのままの場合です。結果に理由が示され、stderr には Error: の行が出力されます。doctor は、チェックが失敗した場合です。結果にどのチェックかが示され、エラーの行は続きません。--json では、どちらもその場合にエラーオブジェクトを出力せず、stdout には結果が出力されます。
--help を付けた場合、不明なコマンドはエラーになりません。ironflock os nosuch --help は ironflock os のヘルプを表示し、終了コード 0 で終了します。複数のマシンでは、コマンドはマシンの中で最も悪い終了コードで終了します(SSH 経由のリモートマシン を参照)。
割り込み
Ctrl-C、SIGTERM、SIGHUP(端末または SSH セッションがなくなったとき)は、ほかのプログラムと同じように、ほとんどのコマンドをすぐに終了させます。エラーの行は出力されず、シェルが受け取るのは 130 です(SIGTERM の後は 143、SIGHUP の後は 129)。いくつかの手順は、これらのシグナルを処理します:
os flashはイメージのダウンロード、書き込み、読み戻しの最中に、os updateは更新バンドルのダウンロードと検証の最中に、次のブロックで止まります。何を残したかを種類interruptedのエラーとして示し、130 で終了します。その場合、os updateは何もインストールしません。os flashが最後のブロックを読み戻した後は、締めくくりの手順を最後まで実行し、0 で終了します。2 回目の 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 の場合は、エラーオブジェクトが入ります。