###導入###
|
最近、lxc exec にいくつかの改良を加えました。 lxc exec は LXD のクライアント ツールです。LXD クライアント API を使用して LXD デーモンと通信し、ユーザーが実行したいさまざまなプログラムを実行します。以下は例です。使用できるもの:
|
私たちの主な目標の 1 つは、lxc exec を ssh と同様にすることです。これは、コマンドをリモートで対話的または非対話的に実行するための標準であるためです。このため、lxc exec をうまく実行するのが少し難しくなります。
1. バックグラウンドタスクの処理
長年にわたる問題は、もちろん、バックグラウンド タスクを適切に処理する方法です。 LXD 2.7 インスタンスの問題の例を次に示します:
バックグラウンドでタスクを実行すると、lxc exec の終了に失敗することがわかります。多くのコマンドがこの問題を引き起こす可能性があります:
リーリー
今、あなたを救えるものは何もありません。 yes は常に stdout に直接書き込みます。
問題の根本は、標準出力が常に開いていることですが、これは、ユーザーが開始したプロセスによって書き込まれたデータが実際に読み取られ、確立した WebSocket 接続を通じて送り返されることを保証するために使用されるため、これが必要です。
これを行う場合は、シェル セッションを実行し、バックグラウンドでプロセスを実行して、すぐにシェルを終了します。申し訳ありませんが、期待どおりに機能しません。
最初の原始的なアプローチは、フォアグラウンド プログラム (シェルなど) が終了したことを検出したら、単純に stdout を閉じることです。しかし、これは思っているほど良いことではありません。この問題は、次のような高速実行プログラムを実行すると明らかになります。
リーリー
ここでは、lxc exec プロセス (および関連する forkexec プロセス。ただし、今は考えないでください。Go setns() は通信しないことを覚えておいてください...) は、stdout 内のバッファリングされたデータがすべて読み取られる前に終了します。 。この状況では、出力が切り捨てられることになりますが、これは誰も望んでいません。 pty バッファリングを無効にする (言っておきますが、これは見栄えがよくなく、期待どおりに動作しません) やその他の奇妙なアイデアなど、問題を解決するためにいくつかの方法を試した結果、私はなんとかいくつかの poll() の「トリック」を乗り越えることができました。ある意味、「トリック」) がこの問題を解決します。これで、最終的にバックグラウンド タスクを実行して完全に終了できるようになりました。写真に示すように:
2. シグナルによって発生した終了コードを報告する
ssh は素晴らしいツールです。しかし、私がいつも嫌いな点の 1 つは、ssh によって実行されたコマンドがシグナルを受信したときに、ssh が常に -1 (終了コード 255) を報告することです。これは、プログラムを終了させた信号を理解したい場合には面倒です。これが、シグナルによる終了を報告するために標準シェル 128 n で使用される規則を最近実装した理由です。ここで、n はエグゼキュータを終了させたセマフォとして定義されています。たとえば、SIGKILL シグナルでは、128 SIGKILL = 137 と表示されます (リーダーの演習として、他の致命的なシグナルの終了コードを計算してください)。したがって、これを行うことができます:
リーリー
次に、SIGKILL をエグゼキューターに送信します (SIGKILL は転送できないため、lxc exec 自体ではありません)。
リーリー
最後にプログラムの終了コードを確認します:
リーリー
###見て。これは明らかに、a) 終了コードが 8 ビットの計算障壁を超えない場合、および b) 実行プログラムが成功を示すために 137 を使用しない場合にのみ機能するようです (なんと...興味深い?!)。どちらの議論も私にはあまり説得力がありません。前者は、致命的なセマフォがこの範囲を超えてはいけないためです。後者の理由は、(i) これはユーザーの問題であり、(ii) これらの終了コードは実際には保持されている (私はそう思います。)、(iii) プログラムをローカルまたは他の場所で実行すると同じ問題が発生するからです。
私が考える主な利点は、実行者に詳細な終了ステータスを報告できることです。シグナルによって強制終了されたすべてのプログラム インスタンスを報告するわけではないことに注意してください。たとえば、プログラムが SIGTERM を処理して正常に終了できる場合、LXD にはこれを検出してプログラムがシグナルによって強制終了されたことを報告する簡単な方法がありません。終了コード 0 が返されるだけです。
3. 順方向信号
これはあまり面白くないかもしれません (または、誰にも分からないかもしれません) が、私は非常に便利だと思います。 SIGKILL のケースでわかるように、SIGKILL は lxc exec コマンド自体ではなくエグゼキューターに送信する必要があると明示しました。プログラム内でSIGKILLを扱えないためです。プログラムができる唯一のことは、今のように...この例のように...すぐに死ぬことです (おわかりでしょう...)。ただし、プログラムは他の多くのシグナル、SIGTERM、SIGHUP'、そしてもちろん SIGUSR1 と SIGUSR2 を処理できます。したがって、lxc exec` では処理できるがエグゼキューターでは処理できないシグナルを送信すると、新しいバージョンの LXD はシグナルをエグゼキューターに転送します。これはスクリプトで非常に便利です。
とにかく、この小さな lxc exec の記事/意味不明な内容が役に立ったことを願っています。 LXD をお楽しみください。クレイジーで美しい野獣と遊んでいます。オンライン実験を試してみてください: https://linuxcontainers.org/lxd/try-it/ 、開発者の方はこちら: https://github.com/lxc/lxd を参照してパッチを送信してください。
CLA に署名する必要はありません。「Signed-off-by」行がある限り、カーネル スタイルに従います。