Rundeckで指定の時間帯に動いてたジョブを特定する

# はじめに
ジョブスケジューラのRundeck便利なんだけど、ジョブ実行履歴を調べるのにActivityの画面だと、この時間帯に動いてたジョブを調べたいみたいなときに地味に困る。実行間隔の短いジョブが混ざってると、Activityの画面で大量のジョブ実行履歴をページングするのはつらい。

例えばシステムメンテナンスでジョブを一時停止したいときの影響範囲を調べたり、Rundeck自体の障害で起動できなかった可能性のあるジョブを調べたりするのに、先週とか先月の同じ時間帯に動いてたジョブの実行履歴をいい感じに調べたい。いいかんじとはジョブ実行履歴じゃなくて、欲しいのはジョブ定義でユニークに集約した情報だったりする。

WebのUIはなくてもジョブ実行履歴とジョブ定義自体はRundeckがメタデータとして持ってるはずなんで、メタデータのDBから直接SQLで抽出すればなんかできそうな予感。
というわけでやってみた。

稼働確認したのは以下のバージョン。

- Rundeck: 2.9.3
- MySQL: 5.7

Rundeckのメタデータはバージョン上がると変わるかもしれない＆バックエンドがMySQL以外の場合は、適宜読み替えて下さい。

# テーブル定義を確認する

とりあえずテーブル一覧を見てみる。

```
mysql> SHOW tables;
+----------------------------+
| Tables_in_rundeck          |
+----------------------------+
| auth_token                 |
| base_report                |
| execution                  |
| job_file_record            |
| log_file_storage_request   |
| node_filter                |
| notification               |
| orchestrator               |
| plugin_meta                |
| project                    |
| rdoption                   |
| rdoption_values            |
| rduser                     |
| report_filter              |
| scheduled_execution        |
| scheduled_execution_filter |
| storage                    |
| workflow                   |
| workflow_step              |
| workflow_workflow_step     |
+----------------------------+
20 rows in set (0.00 sec)
```

`execution` テーブルってのがジョブ実行履歴で、 `date_started` にジョブ開始日時、 `date_completed` にジョブ終了日時が入ってる。
時刻はRundeckのプロセスを動かしてるタイムゾーンなので、JSTならJSTで保存されてます。

```
mysql> DESC execution;
+------------------------------+--------------+------+-----+---------+----------------+
| Field                        | Type         | Null | Key | Default | Extra          |
+------------------------------+--------------+------+-----+---------+----------------+
| id                           | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| version                      | bigint(20)   | NO   |     | NULL    |                |
| abortedby                    | varchar(255) | YES  |     | NULL    |                |
| arg_string                   | longtext     | YES  |     | NULL    |                |
| cancelled                    | bit(1)       | NO   |     | NULL    |                |
| date_completed               | datetime     | YES  | MUL | NULL    |                |
| date_started                 | datetime     | YES  | MUL | NULL    |                |
| do_nodedispatch              | bit(1)       | YES  |     | NULL    |                |
| execution_type               | varchar(30)  | YES  |     | NULL    |                |
| failed_node_list             | longtext     | YES  |     | NULL    |                |
| filter                       | longtext     | YES  |     | NULL    |                |
| loglevel                     | varchar(255) | YES  |     | NULL    |                |
| node_exclude                 | longtext     | YES  |     | NULL    |                |
| node_exclude_name            | longtext     | YES  |     | NULL    |                |
| node_exclude_os_arch         | longtext     | YES  |     | NULL    |                |
| node_exclude_os_family       | longtext     | YES  |     | NULL    |                |
| node_exclude_os_name         | longtext     | YES  |     | NULL    |                |
| node_exclude_os_version      | longtext     | YES  |     | NULL    |                |
| node_exclude_precedence      | bit(1)       | YES  |     | NULL    |                |
| node_exclude_tags            | longtext     | YES  |     | NULL    |                |
| node_filter_editable         | bit(1)       | YES  |     | NULL    |                |
| node_include                 | longtext     | YES  |     | NULL    |                |
| node_include_name            | longtext     | YES  |     | NULL    |                |
| node_include_os_arch         | longtext     | YES  |     | NULL    |                |
| node_include_os_family       | longtext     | YES  |     | NULL    |                |
| node_include_os_name         | longtext     | YES  |     | NULL    |                |
| node_include_os_version      | longtext     | YES  |     | NULL    |                |
| node_include_tags            | longtext     | YES  |     | NULL    |                |
| node_keepgoing               | bit(1)       | YES  |     | NULL    |                |
| node_rank_attribute          | varchar(255) | YES  |     | NULL    |                |
| node_rank_order_ascending    | bit(1)       | YES  |     | NULL    |                |
| node_threadcount             | int(11)      | YES  |     | NULL    |                |
| orchestrator_id              | bigint(20)   | YES  | MUL | NULL    |                |
| outputfilepath               | longtext     | YES  |     | NULL    |                |
| project                      | varchar(255) | NO   |     | NULL    |                |
| retry                        | longtext     | YES  |     | NULL    |                |
| retry_attempt                | int(11)      | YES  |     | NULL    |                |
| retry_execution_id           | bigint(20)   | YES  | MUL | NULL    |                |
| scheduled_execution_id       | bigint(20)   | YES  | MUL | NULL    |                |
| server_nodeuuid              | varchar(36)  | YES  |     | NULL    |                |
| status                       | varchar(255) | YES  |     | NULL    |                |
| succeeded_node_list          | longtext     | YES  |     | NULL    |                |
| timed_out                    | bit(1)       | YES  |     | NULL    |                |
| timeout                      | longtext     | YES  |     | NULL    |                |
| rduser                       | varchar(255) | NO   |     | NULL    |                |
| will_retry                   | bit(1)       | YES  |     | NULL    |                |
| workflow_id                  | bigint(20)   | YES  | MUL | NULL    |                |
| retry_delay                  | varchar(255) | YES  |     | NULL    |                |
| success_on_empty_node_filter | bit(1)       | YES  |     | NULL    |                |
| user_role_list               | longtext     | YES  |     | NULL    |                |
+------------------------------+--------------+------+-----+---------+----------------+
50 rows in set (0.00 sec)
```

`scheduled_execution` テーブルってのがジョブのスケジュール定義で、ジョブ名とかいつ起動するかのcrontabの情報が入っている。

```
mysql> DESC scheduled_execution;
+------------------------------+---------------+------+-----+---------+----------------+
| Field                        | Type          | Null | Key | Default | Extra          |
+------------------------------+---------------+------+-----+---------+----------------+
| id                           | bigint(20)    | NO   | PRI | NULL    | auto_increment |
| version                      | bigint(20)    | NO   |     | NULL    |                |
| arg_string                   | longtext      | YES  |     | NULL    |                |
| date_created                 | datetime      | NO   |     | NULL    |                |
| day_of_month                 | varchar(255)  | YES  |     | NULL    |                |
| day_of_week                  | varchar(255)  | YES  |     | NULL    |                |
| description                  | longtext      | YES  |     | NULL    |                |
| do_nodedispatch              | bit(1)        | YES  |     | NULL    |                |
| exec_count                   | bigint(20)    | YES  |     | NULL    |                |
| execution_enabled            | bit(1)        | YES  |     | NULL    |                |
| filter                       | longtext      | YES  |     | NULL    |                |
| group_path                   | varchar(2048) | YES  |     | NULL    |                |
| hour                         | varchar(255)  | YES  |     | NULL    |                |
| job_name                     | varchar(1024) | NO   |     | NULL    |                |
| last_updated                 | datetime      | NO   |     | NULL    |                |
| log_output_threshold         | varchar(256)  | YES  |     | NULL    |                |
| log_output_threshold_action  | varchar(256)  | YES  |     | NULL    |                |
| log_output_threshold_status  | varchar(256)  | YES  |     | NULL    |                |
| loglevel                     | varchar(255)  | YES  |     | NULL    |                |
| minute                       | varchar(255)  | YES  |     | NULL    |                |
| month                        | varchar(255)  | YES  |     | NULL    |                |
| multiple_executions          | bit(1)        | YES  |     | NULL    |                |
| next_execution               | datetime      | YES  |     | NULL    |                |
| node_exclude                 | longtext      | YES  |     | NULL    |                |
| node_exclude_name            | longtext      | YES  |     | NULL    |                |
| node_exclude_os_arch         | longtext      | YES  |     | NULL    |                |
| node_exclude_os_family       | longtext      | YES  |     | NULL    |                |
| node_exclude_os_name         | longtext      | YES  |     | NULL    |                |
| node_exclude_os_version      | longtext      | YES  |     | NULL    |                |
| node_exclude_precedence      | bit(1)        | YES  |     | NULL    |                |
| node_exclude_tags            | longtext      | YES  |     | NULL    |                |
| node_filter_editable         | bit(1)        | YES  |     | NULL    |                |
| node_include                 | longtext      | YES  |     | NULL    |                |
| node_include_name            | longtext      | YES  |     | NULL    |                |
| node_include_os_arch         | longtext      | YES  |     | NULL    |                |
| node_include_os_family       | longtext      | YES  |     | NULL    |                |
| node_include_os_name         | longtext      | YES  |     | NULL    |                |
| node_include_os_version      | longtext      | YES  |     | NULL    |                |
| node_include_tags            | longtext      | YES  |     | NULL    |                |
| node_keepgoing               | bit(1)        | YES  |     | NULL    |                |
| node_rank_attribute          | varchar(255)  | YES  |     | NULL    |                |
| node_rank_order_ascending    | bit(1)        | YES  |     | NULL    |                |
| node_threadcount             | int(11)       | YES  |     | NULL    |                |
| nodes_selected_by_default    | bit(1)        | YES  |     | NULL    |                |
| orchestrator_id              | bigint(20)    | YES  | MUL | NULL    |                |
| project                      | varchar(255)  | NO   |     | NULL    |                |
| retry                        | longtext      | YES  |     | NULL    |                |
| schedule_enabled             | bit(1)        | YES  |     | NULL    |                |
| scheduled                    | bit(1)        | NO   |     | NULL    |                |
| seconds                      | varchar(255)  | YES  |     | NULL    |                |
| server_nodeuuid              | varchar(36)   | YES  |     | NULL    |                |
| timeout                      | longtext      | YES  |     | NULL    |                |
| total_time                   | bigint(20)    | YES  |     | NULL    |                |
| rduser                       | varchar(255)  | YES  |     | NULL    |                |
| user_role_list               | longtext      | YES  |     | NULL    |                |
| uuid                         | varchar(255)  | YES  |     | NULL    |                |
| workflow_id                  | bigint(20)    | YES  | MUL | NULL    |                |
| year                         | varchar(255)  | YES  |     | NULL    |                |
| retry_delay                  | longtext      | YES  |     | NULL    |                |
| success_on_empty_node_filter | bit(1)        | YES  |     | NULL    |                |
| time_zone                    | varchar(256)  | YES  |     | NULL    |                |
+------------------------------+---------------+------+-----+---------+----------------+
61 rows in set (0.01 sec)

```

# 指定の時間帯に動いてたジョブを特定する

executionから指定の時間帯に開始、または終了したジョブ、または指定の範囲でずっと動いてたジョブを抽出して、
scheduled_executionとJOINして、
scheduled_executionでSELECT DISTINCTして必要な情報を引っ張り出してあげればよさそう。
あとは多少見やすいように文字列加工。

完成品はこちらです。

```sql

SET @from = '2018-08-06 02:00:00', @to = '2018-08-06 03:00:00';

SELECT DISTINCT
 s.uuid,
 LEFT(CONCAT(s.project, '/', s.group_path, '/', s.job_name), 64) AS job,
 LEFT(SUBSTRING_INDEX(s.description, '\n', 1), 10) AS description,
 s.filter, CONCAT(s.seconds, ' ', s.minute, ' ', s.hour, ' ', s.day_of_month, ' ', s.month, ' ', s.day_of_week, ' ', s.year) AS schedule,
 s.next_execution AS next
FROM
 execution AS e 
 LEFT JOIN scheduled_execution AS s
 ON e.scheduled_execution_id = s.id
WHERE
 (e.date_started BETWEEN @from AND @to)
 OR (e.date_completed BETWEEN @from AND @to)
 OR (e.date_started < @from AND e.date_completed > @to)
ORDER BY job;
```

実行結果は多少ぼかしてしか貼れないけど、雰囲気だけお伝えするとこんなかんじ。

```
+------+-------------------+-------------+-------------+-----------------+---------------------+
| uuid | job               | description | filter      | schedule        | next                |
+------+-------------------+-------------+-------------+-----------------+---------------------+
| xxxx | proj1/group1/job1 | job1        | name: batch | 0 3 * * * ? *   | 2018-09-05 13:03:00 |
| xxxx | proj1/group1/job2 | job2        | name: batch | 0 33 * * * ? *  | 2018-09-05 12:33:00 |
```

これでRundeck職人に頼らずに機械的に対象のジョブが特定できますね。
どうぞご利用下さい。