JS7® JobScheduler WorkFlowでの変数利用

# 概要

JS7 JobSchedulerのWorkFlow定義で利用する変数について説明します。
ここでは、基本的な変数を利用の操作、および変数を自由に扱うために必要な環境変数、Order変数の説明をします。

# 前提条件

- JS7 jobscheduler の環境準備、初期設定を済ませていること。
まだの方はこちらから
[JS7® JobScheduler 初期設定、サンプルWorkFlowの登録](https://qiita.com/saitamanokusa/items/2d3162b688329f5ecae2)
- WorkFlowの作成、実行、ログ確認などの基本操作ができること。
  こちらで簡単な操作説明をしています
  [JS7 JobScheduler 初めてのWorkFlow実行](https://qiita.com/saitamanokusa/items/1e5ab48cd2e9d38e035c)
- 本例はAgentがLinux環境であることを前提としています。
WindowsのAgentで設定を行うにはスクリプトの内容をPowerShell用などに置き換えてください。

# WorkFlow における変数について

JobSchedulerでは、WorkFlowの変数を利用することで、例えば下記のようなことが可能となります。

- WorkFlow、JOBの実行時に、変数を渡し、JOBの処理中で参照する。
- 各WorkFlowで利用できる共通変数の定義をする。
- JOBの中での取得した値を変数定義し、後続JOBで利用する。
- 変数の値に応じて、WorkFlowの処理の流れを変える。

# 変数を使ってみる

まず実際に変数を利用した基本的な設定を行ってみます。

## WorkFlowで指定した値をJOBに渡す

Inventoryにて、今回練習用のフォルダ Practiceを作り、その配下の Controller - WorkFlow にて新規にWorkFlow `check_vars`を作成します。

JOBを追加し、下記のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/372e4cdd-90fb-33c0-08c9-881cd8890891.png)


|項目|設定値|
|-|-|
|Name | job1 |
|Label | job1 |
|Title | 空（任意） |
|Documentation | 空 |
|Agent| PrimaryAgent ※任意のものを選択 |
|Return Code| On Success で 0 を指定|
|JobClass | Shell |

Script の欄は、下記コマンドを登録します。

```shell:job1
echo "STR1: $STR1"
```

Environment Variables は下記の登録をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/433cc9a6-9f3d-c669-0466-ad394d3f607d.png)


|Name|Value|
|-|-|
|STR1 | hello |

WorkFlowをDeployし、実行します。
ログをみて、環境変数 `$STR1` で、定義した値が参照できていることを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/8830e1bc-9b93-b1a7-b585-38e1a018ce03.png)


## Job Resource で定義した環境変数を使う

WorkFlow`check_vars`をさらに編集していきます。

WorkFlowの Job Resources にて、 `/Defaults/Default` を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/5308c996-94b4-d880-93ea-5c415aafe782.png)

さらにJOBを追加し、下記のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/4fd359fb-7d6e-ff7e-529c-eff8cf06457b.png)


|項目|設定値|
|-|-|
|Name | job2 |
|Label | job2 |
|Agent| PrimaryAgent ※任意のものを選択 |
|Job Class | Shell |

Script の欄は、下記コマンドを登録します。

```shell:job2
echo "JS7_AGENT_HOME: $JS7_AGENT_HOME"
echo "JS7_JOC_URL: $JS7_JOC_URL"
echo "JS7_JOBSTART_DATE: $JS7_JOBSTART_DATE"
```

WorkFlowをDeployし、実行します。
ログをみて、環境変数 `$JS7_AGENT_HOME`, `$JS7_JOC_URL`, `$JS7_JOBSTART_DATE` の値が参照できていることを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/ae8ebc1a-ad67-45a0-6a58-abdc6da65701.png)


## Order変数を使う

今作ったWorkFlow`check_vars`をさらに編集していきます。

WorkFlow にて Add Variable より Order変数を下記のように定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/ccee18c0-9e3b-652a-dff8-12a5645cd1e5.png)


|Name|Type|Value|
|-|-|-|
|pref| String |saitama |
|code | Number | 11 |

さらにJOBを追加し、下記のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/0f538173-9a26-377d-436f-3d4d855bd0a1.png)

|項目|設定値|
|-|-|
|Name | job3 |
|Label | job3 |
|Agent| PrimaryAgent ※任意のものを選択 |
|Job Class | Shell |

Environment Variables は下記の登録をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/6de6313e-a2f9-d6d6-e60e-1576d45720b7.png)

|Name|Value|
|-|-|
|PREF | $pref |
|CODE | $code |

Script の欄は、下記コマンドを登録します。

```shell:job3
echo "PREF: $PREF"
echo "CODE: $CODE"

# order 変数は直接参照できない
echo "order variable pref: $pref"
echo "order variable code: $code"
```

WorkFlowをDeployし、実行します。
ログをみて、環境変数 `$PREF`, `$CODE` の値が参照でき、Order変数は参照できないことを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/2a6c8647-b94e-1d6c-59d7-9ec85ff10152.png)

また、Order 追加時に、Order変数の値を変更すると、出力される値も変わることを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/161acbcb-2674-d76c-8244-e887c577c54e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/0229d6d3-7d1a-93e6-ed1d-7accc1de91eb.png)

## 後続JOBに変数を渡す

WorkFlow`check_vars`をさらに編集していきます。

最初に作成した `job1`のScriptを下記のように編集します。

```shell:job1
echo "STR1: $STR1"

var="これは${JS7_JOB_NAME}で作成した変数です"
echo "handover=$var">>$JS7_RETURN_VALUES
```

さらにJOBを追加し、下記のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/67cbb923-32c3-af88-bef0-87e5cd5dcdff.png)

|項目|設定値|
|-|-|
|Name | job4 |
|Label | job4 |
|Agent| PrimaryAgent ※任意のものを選択 |
|Job Class | Shell |

Environment Variables は下記の登録をします。

|Name|Value|
|-|-|
|HANDOVER | $handover |

Script の欄は、下記コマンドを登録します。

```shell:job4
echo "HANDOVER: $HANDOVER"
```

WorkFlowをDeployし、実行します。
ログをみて、job1で定義した変数 `$handover`を使ったJOB環境変数 `$HANDOVER` が参照できていることを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/d65b2eaf-6ebb-6c74-3c83-1a67e48d5370.png)

# 変数の種類

上記の変数利用の例で、「環境変数」と「Order変数」という言葉を使いましたが、この２つをもう少し掘り下げて説明します。

## 環境変数とOrder変数の違い

シェルジョブから参照できるのは、あくまで環境変数として定義された値のみです。
Order変数は直接参照できません。
Order変数を参照するためには、そのOrder変数を、JOB環境変数として定義する必要があります。

Order変数は、JOB環境変数の値として使う以外にも、WorkFlowの制御にも使うことができます。
また、例でも示したとおり、シェルジョブの実行結果をOrder変数として動的に定義することも可能です。
（つまりJOBの処理結果に応じて、後続JOBの処理を変えることが可能）

## 環境変数

初めの例で見たとおり、シェルジョブに値を渡すには、環境変数の定義が必要です。
シェルジョブにて環境変数を利用する方法は大きく３種類あります。

- Default (シェルジョブ実行時に自動的に設定される)
- JOB環境変数　（特定JOBのプロパティで指定）
- ジョブリソース　（共通で利用可能なの変数定義）
  - Default  初期設定で組み込む。
  - eMailDefault 初期設定で組み込む。メール通知を行う際に利用
  - その他、用途に応じたカスタマイズ変数の定義が可能

なお、環境変数で指定した値は、データ型がStringとなります。

### Default

Agentでシェルジョブを実行する際、特別な設定なしに利用できる環境変数があります。

変数の例

|変数名|内容|
|-|-|
|JS7_AGENT_HOME|js7-agent home directory|
|JS7_AGENT_WORK_DIR|js7-agent working directory.|
|JS7_RETURN_VALUES|シェルジョブ用の特別な一時ファイルのパス|

詳しくはこちらに載ってます

[Environment Variables that are automatically available to Shell Jobs](https://kb.sos-berlin.com/display/PKB/JS7+-+Job+Environment+Variables#JS7-JobEnvironmentVariables-env_from_shellEnvironmentVariablesthatareautomaticallyavailabletoShellJobs)

### JOB環境変数

個別のJOBで利用できる環境変数を定義できます。
Valueは、直接値を入力する意外にも、既存のOrder変数（WorkFlowで定義した変数、Node引数など）を利用可能です。
シェルジョブ中で、Order変数を参照したい場合は、こちらの指定が必須となります。

### Job Resource

各WorkFlow、Jobにて利用可能な共通変数の定義
値には、定数値以外に、式を利用することも可能

Job Resources/Default を読み込むことで利用できる環境変数の例

|変数名|内容|
|-|-|
|JS7_ORDER_ID|Order ID|
|JS7_WORKFLOW_NAME|実行中のWorkFlow名|
|JS7_JOB_NAME|実行中のJOB名|
|JS7_JOBSTART_DATE|WorkFlow実行開始日時|

初期設定の中で取り込む、`/Defaults/Default`, `/Defaults/eMailDefault` については下記に説明があります。
[Environment Variables from Job Resources for Shell Jobs](https://kb.sos-berlin.com/display/PKB/JS7+-+Job+Environment+Variables#JS7-JobEnvironmentVariables-job_resource_defaultJobResource:Default)

#### JobResource の中身

参考に`/Defaults/Default`の中身を見てみます。

Arguments
JVM ジョブ（JITLなど）で引数として利用できます。
値は式を利用したり、直接入力することも可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/165dad74-cedc-8f37-f9f3-64130c569d83.png)


Environment Variables
シェルジョブにて環境変数として利用できます。
こちらも式や値を入力可能ですが、通常は`$引数名`で指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/1d816abc-f7e1-6e03-b111-b9ac80cf5cab.png)



:::note
基本的には、Arguments側で値を定義、Environment Variables側で引数を参照　とすることで、引数、環境変数ともに共通の値を利用できるようにします
:::

### 環境変数の優先順位

念のため、もし名前がかぶった場合の動作も確認してみました。

1. Job Resource 環境変数(JOB指定) ※最優先
1. Job Resource 環境変数(WorkFlow指定)
1. JOB環境変数
1. デフォルト環境変数

※2つのJobResourceに同一名の環境変数が含まれる場合は、前に指定している側が優先

したがって、環境変数の名前の付け方で注意すべき点は下記のとおり

- デフォルト環境変数との名前重複を避けることは必須
- Job Resource 環境変数とJOB環境変数の名前重複が起こらないよう、Job Resource側は、何らかの命名規則に従って変数名を付ける
  - 種類毎にプレフィックスをつけるなど
  - 同じ種類で使い分け目的ならば名前を揃える（本番用、検証用など）

:::note warn
基本的には、環境変数は名前がかぶらないようにしてください。
:::

## Order 変数

Order変数は、最初の例で示したとおり、環境変数の値として利用したり、WorkFlowの処理の制御にも利用できます。
ここでは大きく3種類の説明します。

- WorkFlowでの定義
- シェルジョブ中での定義
- Node引数

### WorkFlowでの定義

こちらは最初の例で見たパターンです。

- WorkFlow定義時に、変数名、デフォルト値を定義可能。
- Order登録時に、変数名を指定して、値を修正できる。
- Order変数は、空のまま実行することはできません。<br>WorkFlowでの定義時に初期値を空とした場合は、Order時に指定が必須です。
- WorkFlowにて定義のない変数は、Order時に指定できません。

:::note warn
WorkFlowの途中で値の変更はできません。
:::

例えばこんな使い方ができます。

- スケジュールでの定期実行時：Order変数を指定し、バックアップ　処理実行　通知　の３ステップを実行
- 運用によるマニュアル実行時：デフォルト値のまま実行で　処理実行　のみ


### シェルジョブ中での定義

こちらも最初の例で示したパターンです。
利用場面は多いと思いますので、ぜひ使い方を覚えてください。

シェルジョブの中で、環境変数`$JS7_RETURN_VALUES`で指定される一時ファイルに変数定義の内容を追記することで、変数として追加することができます。

```shell
echo "key=value" >> $JS7_RETURN_VALUES
```

:::note
WorkFlow定義の変数と違い、こちらは処理の途中で柔軟に変数の追加や上書きが可能です。
:::

例えば job1, job2, job3 の順で実行される処理にて、下記のように定義した場合

```shell:job1
val="job1_execute"
echo "handover=$val">>$JS7_RETURN_VALUES
echo "handover1=$val">>$JS7_RETURN_VALUES
```

```shell:job2
val="job2_execute"
echo "handover=$val">>$JS7_RETURN_VALUES
echo "handover2=$val">>$JS7_RETURN_VALUES
```

```shell:job3
val="job3_execute"
echo "handover=$val">>$JS7_RETURN_VALUES
echo "handover3=$val">>$JS7_RETURN_VALUES
```

この場合、後続処理では、`$handover`,`$handover1`,`$handover2`,`$handover3` とも利用できます。
なお、同一名は上書きとなるため、`$handover`の値は`job3_execute` となります。

#### 補足 複数行の値の利用

こちらの変数は、基本的には、複数行の文字を送ることはできません。
こちらの手段でできそうだが、、、文字化けする。JVMジョブのみ？
[JS7 - How to pass variables with arbitrary length values to jobs](https://kb.sos-berlin.com/display/PKB/JS7+-+How+to+pass+variables+with+arbitrary+length+values+to+jobs)

#### 参考 未定義の変数対応

後続処理で、未定義の変数名を利用すると、エラーとなるため注意してください。

WorkFlowの先頭のJOBで、変数の初期値を定義するなど工夫すると良いかもしれません。

```shell:initialize
# 変数初期化
echo "handover=">>$JS7_RETURN_VALUES
echo "handover1=">>$JS7_RETURN_VALUES
echo "handover2=">>$JS7_RETURN_VALUES
echo "handover3=">>$JS7_RETURN_VALUES

# 環境変数の確認
printenv | sort 
```
### Node引数

3つ目のNode引数ですが、こちらは使う場面はあまりないかもしれません。

- Node引数は、特定Node（JOB）のみで利用できる引数です。
- 定義した引数を、JOB環境変数の値として指定できます。
- Node引数は、値に変数を指定することはできません。（直接値を指定するのみ）<br>（だからVariant ではなく Argument と区別されている）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/4ae6a303-8d06-5e2b-820e-f3ef64bfa6e5.png)

基本的には、Labelを使って同一Jobを複数定義した場合、処理を分けるために利用します。
（JOB Nameを揃えることで、同一JOBを複数定義できる）

### Order変数の優先順位

こちらも念のため、名前が重複した場合の優先順位を確認してみました。

1. Order時指定のOrder変数　最優先
1. WorkFlow定義のOrder変数(初期値)
1. シェルジョブ中での定義`$JS7_RETURN_VALUES`
1. Node引数

:::note warn
こちらも基本的には名前がかぶらないようにしてください。
:::

# 最後に

環境変数を使えばスクリプトの記述の効率化に、Order変数を使えばWorkFlowを柔軟に定義できるようになります。ぜひマスターしてください。
この記事が参考になれば幸いです。

# 参考

- [JS7 - Variables](https://kb.sos-berlin.com/display/PKB/JS7+-+Variables)
- [JS7 - Assignment of Variables](https://kb.sos-berlin.com/display/PKB/JS7+-+Assignment+of+Variables)
- [用語](https://kb.sos-berlin.com/display/PKB/JS7+-+Terminology)