KnowHow

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

Epilogスクリプトについて追加

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

Epilogスクリプトでジョブタイプ(インタラクティブ実行 vs バッチ処理)を判別し、適切なプロセスクリーンアップを行うスクリプトは以下のように実装できます。SLURMの環境変数と条件分岐を活用します。

#!/bin/bash
# SLURM Epilogスクリプト(/opt/slurm/etc/scripts/epilog.d/20_clean_processes.sh)

# ログ設定
LOG_FILE="/var/log/slurm/epilog_clean.log"
echo "[$(date)] Epilog started for job: $SLURM_JOB_ID" >> $LOG_FILE

# ジョブタイプ判別
if [[ "$SLURM_JOB_NAME" == "interactive" ]]; then
    # インタラクティブジョブ(srun/salloc): ユーザーの全プロセスを削除
    echo "Interactive job detected. Cleaning all user processes..." >> $LOG_FILE
    pkill -9 -u $SLURM_JOB_USER
    pgrep -u $SLURM_JOB_USER | xargs -r kill -9
else
    # バッチジョブ(sbatch): SLURMジョブIDに関連するプロセスのみ削除
    echo "Batch job detected. Cleaning job-related processes..." >> $LOG_FILE

    # SLURMジョブIDに関連するプロセスの特定と削除
    ps aux | awk -v jobid="$SLURM_JOB_ID" \
        '$0 ~ jobid && $1 == ENVIRON["SLURM_JOB_USER"] {print $2}' | \
        xargs -r kill -9

    # scontrol listpidsで管理プロセスを削除(SLURM 23.02以降)
    if command -v scontrol &> /dev/null; then
        scontrol listpids $SLURM_JOB_ID | \
        awk '/^[0-9]+/{print $1}' | \
        xargs -r kill -9
    fi
fi
# クリーンアップ完了ログ
echo "[$(date)] Cleanup completed for job: $SLURM_JOB_ID" >> $LOG_FILE

実装手順
スクリプト配置:

sudo mkdir -p /opt/slurm/etc/scripts/epilog.d
sudo nano /opt/slurm/etc/scripts/epilog.d/20_clean_processes.sh

権限設定:

sudo chmod 755 /opt/slurm/etc/scripts/epilog.d/20_clean_processes.sh
sudo chown slurm:slurm /opt/slurm/etc/scripts/epilog.d/20_clean_processes.sh

slurm.conf設定:

Epilog=/opt/slurm/etc/scripts/epilog.d/*
PrologFlags=Alloc
sudoers設定(必要な場合):
# /etc/sudoers.d/slurm_epilog
slurm ALL=(ALL) NOPASSWD: /usr/bin/pkill
slurm ALL=(ALL) NOPASSWD: /usr/bin/pgrep

動作説明
インタラクティブジョブ時(srun/salloc)
判別方法: $SLURM_JOB_NAMEが"interactive"の場合

処理内容:

pkill -9 -u $USERでユーザー全プロセスを強制終了

pgrepで残存プロセスを検出し追加削除

バッチジョブ時(sbatch)
判別方法: 上記以外の場合

処理内容:

ps auxでジョブIDを含むコマンドラインのプロセスを検出

scontrol listpids(SLURM 23.02以降)で管理プロセスを取得

検出したPIDを強制終了

検証方法
テストケース1: インタラクティブジョブ

salloc -N 1 --job-name=interactive

# 別ターミナルでプロセス起動
ssh node1 "sleep 1000" &
# ジョブ終了後、プロセスが削除されていることを確認

テストケース2: バッチジョブ

sbatch --wrap="sleep 1000"
# ジョブ終了後、関連プロセスのみ削除されることを確認

注意事項
セキュリティ:

Epilogスクリプトはroot権限で実行されるため、権限昇格のリスクを排除する設計が必要

kill -9は最終手段として使用し、可能な限りSIGTERM(kill -15)を優先

パフォーマンス:

大規模クラスタではプロセス検出処理に時間がかかるため、xargs -rで空入力時のエラーを防止

/var/log/slurm/ディレクトリのログローテーション設定を推奨

SLURMバージョン:

scontrol listpidsはSLURM 23.02以降で利用可能

旧バージョンではsshpd.shなどの代替スクリプトが必要8

この実装により、ジョブタイプに応じた適切なプロセスクリーンアップが自動化されます。

Appendix

ジョブタイプの判別方法で、BatchFlagを使うスクリプト
※バッチジョブのは、BatchFlag=1となる。
※インタラクティブジョブはBatchFlag=0となる。

#!/bin/bash

# Epilogスクリプト内での実装例

# ジョブ情報を取得
# JOB_INFO=$(scontrol show job $SLURM_JOB_ID)
JOB_INFO=$(sudo scontrol show job $SLURM_JOB_ID)

# BatchFlagの値を抽出
BATCH_FLAG=$(echo "$JOB_INFO" | grep -oP 'BatchFlag=\K\d+')

if [[ "$BATCH_FLAG" == "1" ]]; then
    # バッチジョブの場合: ジョブIDに関連するプロセスのみ削除
    echo "Batch job detected. Cleaning job-related processes..." >> /var/log/epilog.log
    pkill -9 -f $SLURM_JOB_ID
else
    # インタラクティブジョブの場合: ユーザ全プロセスを削除
    echo "Interactive job detected. Cleaning all user processes..." >> /var/log/epilog.log
    pkill -9 -u $SLURM_JOB_USER
fi

動作確認方法
バッチジョブ(BatchFlag=1)の場合

sbatch --wrap="sleep 60"
# Epilogログ確認:
# "Batch job detected. Cleaning job-related processes..."

インタラクティブジョブ(BatchFlag=0)の場合

salloc -N 1
# 別ターミナルでプロセス起動
ssh node1 "sleep 1000" &
exit
# Epilogログ確認:
# "Interactive job detected. Cleaning all user processes..."

制約事項
ジョブ終了後の情報取得:

ジョブが完全に終了した後ではscontrol show jobが情報を返さないため、Epilogスクリプトの実行タイミングが重要です17。

クラスタ設定依存:

BatchFlagはsbatchで投入されたジョブでのみ1が設定されます8。

salloc/srunで開始されたジョブは0になります。

パフォーマンス影響:

大規模クラスタでscontrolコマンドを頻繁に実行すると、slurmctldに負荷がかかる可能性があります。

代替方法(環境変数を利用)
SLURM_SCRIPT_CONTEXT環境変数で実行コンテキストを判別可能13:

#!/bin/bash

case $SLURM_SCRIPT_CONTEXT in
    epilog_slurmctld)
        echo "Controller-level cleanup" ;;
    epilog_slurmd)
        if [[ $(sudo scontrol show job $SLURM_JOB_ID | grep -c 'BatchFlag=1') -gt 0 ]]; then
            # バッチジョブ処理
        else
            # インタラクティブ処理
        fi ;;
esac

Appendix2

Epilogスクリプトはジョブが完全に終了する前の段階で実行されるため、scontrol show jobコマンドでジョブ情報を取得可能です。Slurmの動作仕様と検索結果47から、以下のポイントが明らかです:

Epilogスクリプトの実行タイミング
ジョブ終了直後の処理:

Epilogスクリプトはジョブ終了直後(リソース解放前)に実行されます。

この時点ではジョブ情報がSlurmにまだ保持されているため、scontrol show jobで情報取得が可能です14。

具体的な実行順序:

flowchart LR
ジョブ終了 --> Epilog実行 --> リソース解放 --> ジョブ情報削除
Epilogは「ジョブ終了」と「リソース解放」の間に位置します47

実装上の注意点
情報取得可能な期間:

# Epilogスクリプト内で有効な操作例
JOB_INFO=$(scontrol show job $SLURM_JOB_ID)  # ← 正常に動作

この時点ではジョブ情報が残存しているため、BatchFlagなどの情報取得が可能3。

ジョブ情報消失後の操作:

# ジョブ完全終了後(例:ユーザー手動実行時)
scontrol show job 完了済み_JOB_ID  # ← "Invalid job id"エラー

リソース解放後は情報が削除されるため、Epilog外での操作は不可4。

補足情報(検索結果から)
AWS ParallelClusterのケース2:

Epilogスクリプトの実行時間はジョブ実行時間に含まれるため、BatchStartTimeout設定(デフォルト3分)に注意が必要。

複数ノード対応7:

# マルチノードジョブの場合のEpilog処理例
srun -N $SLURM_JOB_NUM_NODES /path/to/cleanup.sh
全ノードでEpilogスクリプトが並列実行されるため、分散処理が必要。

これらの仕様を理解した上で、Epilogスクリプト内でscontrolを活用した柔軟なクリーンアップ処理を実装できます。