Kompira のセッション機能を利用して対話的にコマンドを実行する

本稿では、Kompira Enterprise のセッション機能を用いて、対話的に Linux コマンドを実行する方法をご紹介します。

※ 本稿は Kompira Enterprise 1.6系に準拠したジョブフロー結果を記載しています。


動作確認環境

本稿は、以下の環境で検証しています。

ソフトウェア バージョン
Kompira Enterprise 1.5.5.post7
OS CentOS 7.8.2003

または

ソフトウェア バージョン
Kompira Enterprise 1.6.2.post4
OS CentOS 8.2.2004

または

ソフトウェア バージョン
Kompira Enterprise 1.6.8
OS CentOS Stream 8

はじめに

Kompira Enterprise のジョブフローを用いてコマンドを実行する際には、[“コマンド”] というように [ ] で囲みます。この場合、各 [ ] 内のコマンドは別のセッションとして実行されます。

例えば次のようなジョブフローを見てみましょう。

["date"] ->
["export LANG=C; date"] ->
["date"]

この実行結果は次のようになります。

2023年 6月 5日 月曜日 10:41:56 JST
Mon Jun  5 10:41:56 JST 2023
2023年 6月 5日 月曜日 10:41:56 JST

※ Kompira Enterprise 1.6系では、print しなくとも実行したコマンドの結果が出力されます。

date コマンドの出力がロケールを明示的に C ロケールに変更した2行目だけ英語になっているのがお分かりになると思います。またジョブフローにおける2行目で設定したロケールが3行目の date コマンドを実行する際に引き継がれておらず、実行結果の3行目を見ると改めて日本語出力になっています。これはつまり各行がそれぞれ別のセッションとして実行されていることを示しています。
逆に同一セッションで行わなければならない局面では、session ブロックを利用して記述します。

session ブロック

session ブロックは以下のような形式で記述します。

{ session セッションチャネル名 |
  ジョブフロー
}

セッションの途中の状態では接続先のリモートサーバーとのやり取りをセッションチャネルを通じて行います。session ブロック終了時、$RESULT にはセッションチャネルが格納され、その data 属性に未読み込みのデータが格納された状態になります。またセッションが成功した場合には、session ブロック終了後に $STATUS に0が格納されます。

例えば、以下のような例を考えてみます。

[__node__ = ./server1] ->
{ session s |
    [s.send: "date\n"] ->
    print("1回目の出力") -> 
    <s> ->
    [s.send: "export LANG=C; date\n"] ->
    print("2回目の出力") ->
    <s> ->
    [s.send: "date\n"] ->
    print("3回目の出力") ->
    <s>
} =>
{ if $STATUS == 0 |
  then:
    [response = $RESULT.data] ->
    print(response) ->
    print("セッションが正常に終了しました")
  else:
    print("セッション中に異常が発生しました")
}

この場合の実行結果は、次のようになります。

※バージョン 1.6.8 以降では、システム設定の「コマンド表示可否」(showCommandEnabled)のデフォルト値がFalse に変更になりました。システム設定のコマンド表示可否をTrue に設定し、コマンド表示形式を指定することでセッションブロックでの実行箇所に特定の文字列を表示することが可能です。詳しくは Kompira Enterprise ドキュメント「2.7.4. システム設定」を参照してください。

1回目の出力
2023年 6月 5日 月曜日 10:33:33 JST
2回目の出力 
Mon Jun  5 10:33:33 JST 2023
3回目の出力
Mon Jun  5 10:33:33 JST 2023
 
セッションが正常に終了しました

[“コマンド”] の場合とは異なり、ジョブフロー中の2回目の date コマンドの直前に設定された LANG が3回目の date コマンドの実行時にも有効になっているのがわかると思います。

接続先サーバーとの対話

コマンドを実行した結果に応じてコマンドを投入したい場合は、セッションチャネルにおいてガード式を利用することで指定した応答を待つようにします。具体的には、上記の例でセッションの値を拾う際に <s> としたところを、<s ?? g”*]# “> のように書きます。この場合、メッセージキューの先頭から順にオブジェクトがマッチするかどうかを調べ、マッチした場合にそれまでのオブジェクトを破棄して、マッチしたオブジェクトを受信します。

ここでは

[user@server log]#

のようなシェルログインした場合のプロンプトが返ってくるのを待ちます。

g"*]# "

の部分は、glob のパターンリテラルを使用しており、”*]# ” で上記のようなプロンプトにマッチさせるようにしています。

ジョブフローにすると、例えば以下のようになります。

[
    __node__ = ./server1,
    __use_pty__ = true
] ->
{ session s |
    [s.send: "export LANG=ja_JP.UTF-8; date\n"] ->
    print("1回目の出力") -> 
    <s ?? g"*]# "> ->
    [s.send: "export LANG=C; date\n"] ->
    print("2回目の出力") -> 
    <s ?? g"*]# "> ->
    [s.send: "export LANG=ja_JP.UTF-8; date\n"] ->
    print("3回目の出力") -> 
    <s ?? g"*]# ">
} =>
{ if $STATUS == 0 |
  then:
    [response = $RESULT.data] ->
    print(response)
    print("セッションが正常に終了しました。")
  else:
    print("セッション中に異常が発生しました。")
}

実行結果は次のようになります。

1回目の出力
export LANG=ja_JP.UTF-8; date
[user@server ~]# export LANG=ja_JP.UTF-8; date
2023年  6月  5日 月曜日 10:46:33 JST
2回目の出力
[user@server ~]# export LANG=C; date
Mon Jun  5 10:46:33 JST 2023
3回目の出力 
[user@server ~]# export LANG=ja_JP.UTF-8; date
2023年  6月  5日 月曜日 10:46:33 JST
[user@server ~]# 
セッションが正常に終了しました。
TOP