KnowHow

技術的なメモを中心にまとめます。
検索にて調べることができます。

SLURMのジョブ終了後にクリーンアップを実行する方法(Epilogスクリプト)

登録日 :2025/03/08 08:17
カテゴリ :SLURM

Epilogスクリプトを利用する方法
Epilogスクリプトは、SLURMジョブが終了した際に、ジョブが割り当てられた各計算ノードで必ず実行されるスクリプトを設定できます。ジョブが正常終了、失敗、キャンセル、またはタイムアウトなどで終了した場合に実行される。各ノードで個別に実行される。

1. Epilogスクリプトを作成する

#!/bin/bash

# ジョブに関連するプロセスを終了
job_id=$SLURM_JOB_ID
pkill -9 -u $USER -f $job_id

# FLUENTなどの特定のプロセスを終了
pkill -9 -u $USER fluent

# ローカルディスクのクリーンアップ
rm -rf /mnt/localdisk/*

# クリーンアップログの記録
echo "Cleanup completed for job $job_id" >> /var/log/slurm/cleanup.log

2. SLURMの設定ファイル(通常は/etc/slurm/slurm.conf)にEpilogスクリプトのパスを指定します

Epilog=/path/to/epilog_script.sh
ex) Epilog=/etc/slurm/epilog_script.sh

複数のEpilogスクリプトがある場合は、ディレクトリ指定も可能

Epilog=/opt/slurm/etc/scripts/epilog.d/*
ex)Epilog=/etc/slurm/epilog.d/*

この設定により、指定されたディレクトリ内のすべてのスクリプトがアルファベット順に実行されます
または、以下のように接頭語をつけて配置します。

/opt/slurm/etc/scripts/epilog.d/10_cleanup.sh
/opt/slurm/etc/scripts/epilog.d/20_finalize.sh

Epilogスクリプトは通常root権限で実行されるため、システムリソース(例: ローカルディスクのクリーンアップや残存プロセスの削除)へのアクセスが可能です。

複数ノードにまたがるジョブの場合、各ノードで個別にEpilogスクリプトが実行されるため、ノード固有のクリーンアップ処理が可能です。

Epilogスクリプト内で、SLURMが提供する環境変数(例:SLURM_JOB_ID, SLURM_NODELIST)を使用することで、ジョブやノードの情報にアクセスし、適切なクリーンアップ処理を行うことができます

注意点として、Epilogスクリプトの実行時間はジョブの実行時間に影響するため、効率的なスクリプト設計が重要です(長時間の処理を含むと、ジョブ終了後のリソース解放が遅れる可能性があります)。また、少なくとも1つのEpilogスクリプトがフォルダ内に存在する必要があります2。

これらの特徴により、Epilogスクリプトは並列計算の複数ノードに対して効果的にクリーンアップ処理を実行できます。

Appendix 1

Epilogスクリプトはsbatchだけでなく、srunやsallocの終了時にもクリーンアップを実行することができます。ただし、いくつかのポイントを理解しておく必要があります。

Epilogスクリプトの動作範囲

sbatchの場合:

sbatchで投入されたジョブが終了すると、そのジョブに割り当てられた各ノードでEpilogスクリプトが実行されます。

これは、ジョブ全体の終了時に実行されるため、複数ノードにまたがるジョブでも各ノードでクリーンアップが行われます。

srunの場合:

srunはジョブステップ(job step)を作成します。Epilogスクリプトは、ジョブ全体ではなく、このジョブステップの終了時にも適用されます。

例えば、sallocでノードを確保し、その後に複数回srunを実行した場合、それぞれのsrun終了時にEpilogスクリプトが呼び出されます。

sallocの場合:

sallocはインタラクティブなジョブ割り当てを作成します。この割り当てが終了したときにEpilogスクリプトが実行されます。

ただし、割り当て中に実行された個々のsrunコマンドに対してもEpilogスクリプトが呼び出される場合があります。

実装上の注意点

Epilogスクリプトの種類:
SLURMでは、以下のような異なる文脈でEpilogスクリプトが実行されます(環境変数SLURM_SCRIPT_CONTEXTで識別可能)57:

epilog_slurmctld: ジョブ全体の終了時にSlurmコントローラ(slurmctld)によって呼び出される。

epilog_slurmd: 各ノードでジョブ終了時に呼び出される。

epilog_srun: 各srunコマンド終了時に呼び出される。

複数ノード対応:

Epilogスクリプトは各ノードで個別に実行されるため、ノード固有のクリーンアップ処理(例: ローカルディスクや残存プロセスの削除)が可能です。

リソース管理:

Epilogスクリプトはジョブ割り当てが解放される前に実行されるため、まだそのノード上のリソース(CPUやメモリ)にアクセス可能です。

Epilogスクリプト設定例

以下は、複数ノードやsrun/salloc/sbatchすべてに対応したクリーンアップ用Epilogスクリプトの例です:

#!/bin/bash

# ログファイル設定
log_file=/var/log/slurm/epilog_cleanup.log

# ログ記録
echo "Running Epilog on node: $(hostname)" >> $log_file
echo "Job ID: $SLURM_JOB_ID, User: $SLURM_JOB_USER" >> $log_file

# 残存プロセスのクリーンアップ
pkill -9 -u $SLURM_JOB_USER

# もしいくは、残存プロセスの削除(ジョブIDに関連するもののみ)
pkill -9 -u $SLURM_JOB_USER -f $SLURM_JOB_ID

# ローカルディスククリーンアップ(例: NVMe領域)
rm -rf /mnt/localdisk/*

echo "Cleanup completed for Job ID: $SLURM_JOB_ID on node: $(hostname)" >> $log_file
設定方法

スクリプトを作成し、適切なパーミッションを設定します:

chmod +x /opt/slurm/etc/scripts/epilog.d/cleanup.sh

SLURM設定ファイル(通常は /etc/slurm/slurm.conf)でEpilogディレクトリを指定します:

Epilog=/opt/slurm/etc/scripts/epilog.d/*

SLURMデーモンを再起動して設定を反映させます:

sudo systemctl restart slurmctld slurmd
# もしいくは、sudo scontrol reconfigure

結論
Epilogスクリプトは、sbatch, srun, sallocすべての終了時に対応可能です。

スクリプトは各ノードで個別に実行されるため、並列計算ジョブや複数ノード環境でも適切なクリーンアップが可能です。

必要に応じて、環境変数(例: SLURM_SCRIPT_CONTEXT, SLURM_JOB_ID, SLURMD_NODENAME)を活用して柔軟な処理を組み込むことができます。

注意点
失敗時の影響:

Epilogスクリプトが失敗すると、そのノードがDRAIN状態になる場合があります。そのため、エラーハンドリングを適切に実装してください。

Prologとの組み合わせ:

ジョブ開始前にPrologスクリプトを使用して環境を準備し、終了時にEpilogスクリプトでクリーンアップすることで一貫性を保てます。

テストと検証:

本番環境に適用する前に十分なテストを行い、意図しないシステム変更やリソース削除が発生しないことを確認してください。

この仕組みにより、ジョブ終了時に計算ノード上で確実にクリーンアップ処理を自動化できます。

Appendix2

pkill -9 -u $SLURM_JOB_USERコマンドは、特定のJOBIDに紐づくプロセスだけを削除することはできません。このコマンドは、指定されたユーザー($SLURM_JOB_USER)が所有するすべてのプロセスを強制終了します。

特定のJOBIDに関連するプロセスのみを終了させるには、以下のような方法を使用する必要があります:

SLURMが提供する環境変数を利用する:

pkill -9 -f $SLURM_JOB_ID

これにより、プロセス名やコマンドラインにジョブIDが含まれるプロセスのみが終了します。

scontrolコマンドを使用してジョブの詳細情報を取得し、プロセスIDを特定する:

scontrol show job $SLURM_JOB_ID | grep ProcessId | awk '{print $1}' | xargs kill -9

psコマンドとgrepを組み合わせて、特定のジョブに関連するプロセスを特定し、それらのみを終了させる:

ps aux | grep $SLURM_JOB_ID | grep -v grep | awk '{print $2}' | xargs kill -9

これらの方法を使用することで、特定のJOBIDに関連するプロセスのみを終了させることができます。ただし、ジョブの性質や実行環境によっては、関連するすべてのプロセスを完全に特定し終了させることが難しい場合もあるため、注意が必要です。