Workiva スクリプトは、メモリ、CPU、ディスク使用状況、実行時間を含む各スクリプト実行で使用されるリソースを自動的に監視します。スクリプトが構成リソースの制限を超えると、Scripting はプラットフォームの安定性を維持しながらスクリプトの安全な停止を試みます。また、スクリプトを完全に停止させる前に、スクリプトをクリーンアップして閉じる時間をスクリプトに与えることで、ユーザーの混乱を最小限に抑えます。
この記事では、スクリプトによる終了シナリオの処理方法、ログに表示される詳細、参照スクリーンショットについて説明します。
すべてのシステム制限の詳細については、Workiva スクリプトの制限 を参照してください。
シナリオ
| シナリオ | 動作 | ログの詳細 |
| 非常に短い実行 | 正常実行 | リソース使用状況のデータ記録なし |
| 正常終了 | 正常実行 | リソースの使用状況の概要が記録されます。 |
| メモリ制限の超過 | 強制終了 | メモリのしきい値を超え、平均およびピーク使用状況を表示します。 |
| ディスク上限超過 | 強制終了 | ディスクのしきい値を超え、平均およびピーク使用状況を表示します。 |
| 割り当て時間の超過 | 強制終了 | 実行時間の超過と使用時間の合計を表示します。 |
| マニュアルキャンセル | 強制終了 | リソースの完全解放、リソースの概要記録 |
| 予期せぬ終了 | 穏やかでない終了 | 部分的または不完全な使用状況のデータレコード |
リソース制限を自動的に実施し、詳細なログ(以下のスクリーンショットに表示)を提供することで、Workiva Scriptingは、自動化スクリプトを構築し最適化する開発者のためのプラットフォームの信頼性と透明性の両方を保証します。
実行が正常に完了した場合の終了
スクリプトが制限を超えることなく正常に完了すると、ログには、メモリ、CPU、ディスク、および実行時間全体の平均使用状況とピーク使用状況を示すリソース使用概要 が含まれます。この情報により、正常に完了した実行のパフォーマンス特性が可視化されます。
メモ: スクリプトの実行が非常に速い場合(たとえば、1秒未満)、リソースのサンプリングが行われないことがあります。この場合、リソースの使用状況データはログにレポートされません。
スクリプトの実行速度が速すぎてサンプルできません。
スクリプトの終了が速すぎる場合、モニターは使用状況データを取得できません。
スクリプトは正常に閉じます。
スクリプトが制限を超えることなく完了した場合、リソースの使用状況がログに完全に表示されます。
制限を超えた場合の終了
スクリプトの実行が構成された制限 (メモリ、ディスク使用状況、割り当て時間など) を超えると、スクリプトは次のように動作します:
- スクリプトの安全な停止を試みる-制限を超えると、スクリプトはまず終了シグナル (SIGTERM) を送信し、スクリプトをクリーンアップして 15 秒以内に閉じます。
- スクリプトが15秒以内に閉じない場合、スクリプトはSIGKILLシグナルを送信し、クリーンアップを許可せずにプロセスを直ちに停止します。これは強制終了であり、実行は失敗ステータス(ログに赤で表示)で完了します。このステータスは、スクリプト システム エラーを示します。
- ログには、どの制限に達したかが表示され、スクリプトのリソース使用状況が要約されます。
次のセクションでは、これらのシグナルを処理するコードがない状態でスクリプトが制限を超えるとどうなるかの例を示します。これらのシグナルに優雅に応答するようにスクリプトを修正する方法については、スクリプトでシステムシグナルを処理する を参照してください。
メモリ制限の超過
スクリプトが構成されたメモリ制限を超えた場合、ログには終了理由と超過したしきい値の詳細が含まれます。
ディスク使用量の上限を超えました。
スクリプトが構成されたディスク使用量の制限を超えた場合、ログには終了理由と制限に達した時のディスク使用状況の詳細が含まれます。
割り当て時間を超過
スクリプトが構成された割り当て時間を超過した場合、ログには終了の理由と記録された総実行時間が含まれます。
ユーザーによる実行キャンセル時の終了
ユーザーがマニュアルで実行をキャンセルした場合、スクリプトはまず割り込み信号(SIGINT)を送信してスクリプトの停止を知らせます。スクリプトは15秒以内にクリーンアップ、保存、ロールバックを行い、シャットダウンします。この15秒の猶予期間の後、上記と同じシーケンスが実行されます。スクリプトがクリーンアップを完了するために、さらに15秒間の終了信号(SIGTERM)が送信され、スクリプトがまだ終了していない場合は最終キルシグナル(SIGKILL)が送信されます。
下の画像は、割り込みシグナルを処理するコードを含まないスクリプトが実行されたときに、スクリプトログがどのように表示されるかを示しています。
これらのシグナルに優雅に応答するようにスクリプトを修正する方法については、スクリプトでのシステム シグナルの処理 を参照してください。
予期しない終了
まれに、スクリプトがスクリプト システムで消費量を監視できる速度よりも速くメモリを消費した場合などには、システムが制限を超えたことを発見する前にスクリプトを終了することがあります。このような場合、スクリプトでは不完全な使用状況レポートが記録され、終了前に収集されたデータ ポイントのみが表示されます。
スクリプトでのシステムシグナルの処理
シグナルを処理することで、スクリプトがシステムによってキャンセルまたは停止されたときに、スクリプトをきれいに閉じることができます。システム シグナルをキャッチして応答することで、スクリプトはリソースを解放して作業を保存し、強制終了されることなく(たとえば、ステータスが「完了」とレポートされたときに)優雅に閉じることができます。
ユーザーがスクリプトをキャンセルしたり、プラットフォームの制限を超えたりしてスクリプトが停止すると、スクリプトは中断、終了、およびkillシグナルを送出します。 中断、終了、キルシグナルがどのようにトリガーされるかについては、前述のセクションを参照してください。
スクリプトシグナルとその処理方法
このセクションでは、これらのシグナルを処理するために使用できるコードブロックと完全な例を提供します。
シグナルハンドラを小さく保ち、シャットダウン時に常に実行されるtry/finally ブロックを使用して、クリーンアップを一箇所で処理することができます。これにより、スクリプトは予測可能で保守しやすくなります。
スクリプト内でシグナルを処理するための全体的な構造は、どのシグナルを受信しても同じです:
- ファイルの先頭: モジュールをインポートし、ハンドラを定義します。
- 初期化の初期化: 作業を行う前にハンドラを登録します。
- 作業の周辺: メインコードを
try/finallyブロックで囲むと、クリーンアップが常に実行されます。
ユーザーが実行をキャンセル (SIGINT)
これは、ユーザーがスクリプト実行をキャンセルするためにキャンセル をクリックしたときに発生します。
--- Top of file --- import signal, sys # Tiny handler: request immediate, graceful exit def _graceful_exit(signum, frame): print("SIGINT received: cancel requested."). クリーンアップ...") raise SystemExit(0) # --- 初期化初期化 --- signal.signal(signal.SIGINT, _graceful_exit) 作業の周辺(ファイル後半):
を試してみてください:# 長く実行された作業はここで ... 最終確認:print("Final cleanup before exit") # ファイルを閉じたり、記録をフラッシュしたりするための中心的な場所。 下の画像は、割り込みシグナル(SIGINT)を処理したときのスクリプトログの表示です。
KeyboardInterrupt を直接処理します。
Workivaスクリプトは、SIGINTがメインスレッドに配信されると、KeyboardInterrupt も発生させます。try ブロックでこの例外をキャッチし、_graceful_exit() で定義されたクリーンアップパスを呼び出すことができます。
try:try: # ここで長時間実行 ... except KeyboardInterrupt: print("KeyboardInterrupt received: cleaning up before exit...") _graceful_exit(None, None) finally:ファイルを閉じたり、ログをフラッシュしたりするための # 中心的な場所 print("終了前の最終クリーンアップ") 下の画像は、割り込みシグナルをキーボード割り込みで処理した場合のスクリプトログの表示です。
猶予期間(SIGTERM)後に停止するスクリプト終了シグナル
スクリプトがスクリプトに停止を要求します(例:制限を超えた後)。あなたのスクリプトには終了までの短い猶予期間があります。
--- ファイルの先頭 --- def _graceful_term(signum, frame): print("SIGTERM received: platform requested termination. 終了します...") raise SystemExit(0) # --- 初期化の初期化 --- signal.signal(signal.SIGTERM, _graceful_term) 下の画像は、終了シグナル(SIGTERM)が処理されたときにスクリプトの記録がどのように表示されるかを示しています。
スクリプトの終了シグナル(SIGKILL)
猶予期間中にスクリプトが閉じないと、スクリプトはSIGKILLを送信します。 SIGKILL をキャッチすることはできません。SIGINT/SIGTERMで速やかに閉じて、最終確認 ブロックがkillが発生する前に実行できるようにしてください。
前のセクションのスクリーンショットは、kill シグナルの結果としてログがどのように表示されるかを示しています。
完全な例 (コピー貼り付け準備完了)
このテンプレートは、最小限のハンドラを登録し、最終的に でクリーンアップを一元化します。Workiva Scriptingに貼り付け、マークした部分をあなたのロジックに置換してください。
コードを追加する場所# ===== YOUR CODE STARTS HERE ===== のサンプルループを実際のタスクに置換してください。プラットフォームがSIGKILLにエスカレートする前にスクリプトが最終確認 ブロックをヒットできるように、非常に長い中断不可能な呼び出しは避けてください。
"""Workivaスクリプトテンプレート: 最小限のハンドラ + finallyでクリーンアップ - 小さなハンドラ SIGINT/SIGTERMでSystemExit(0)を発生 - スクリプトの停止方法に関係なく、クリーンアップのために単一のfinallyブロックを実行 - コードを小さく、予測可能に保つ """ import signal import time # --- シグナルハンドラ(小さなまま) --- def _graceful_exit(signum, frame): print("SIGINTを受信: キャンセルが要求されました。クリーンアップ...") raise SystemExit(0) def _graceful_term(signum, frame): print("SIGTERMを受け取りました: プラットフォームが終了を依頼しました。終了します...") raise SystemExit(0) # --- 重い作業をする前にハンドラを登録する --- signal.signal(signal.SIGINT, _graceful_exit) signal.signal(signal.SIGTERM, _graceful_term) # --- スクリプトの主な作業 --- def main(): print("作業を開始します...") # ===== あなたのコードはここから始まる ===== # 長時間実行ループの例。実際のロジックに置換します。 for i in range(1, 1_000_000):# 作業単位のシミュレーション (実際のロジックに置換) print(f "Working on item{i}...") time.sleep(1) # ===== YOUR CODE ENDS HERE ===== if __name__ == "__main__": try: main() finally:# 常に実行される最終クリーンアップ(SIGINT/SIGTERM時を含む) print("閉じる前の最終クリーンアップ")