You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Slurmd节点计算输出存储至数据库?

Slurm作业输出文件存储到PostgreSQL的解决方案

一、Slurm内置功能说明

Slurm 的 slurmdbd 组件仅负责存储作业记账元数据(如作业ID、提交用户、资源分配、运行时长、状态等),不支持直接将作业的 stdout/stderr 输出文件写入数据库。作业输出默认会留存于计算节点本地存储,或用户指定的路径。

二、基于PostgreSQL的自定义实现方案

结合你已部署的 PostgreSQL 环境,以下是几种可落地的思路:

1. 作业完成后自动触发上传脚本

利用 Slurm 的 Epilog 机制,在作业结束时自动执行脚本,将输出文件内容写入 PostgreSQL:

  • 在 slurm.conf 中全局配置作业结束后执行的脚本:
    Epilog=/opt/slurm/scripts/upload_job_output.sh
    
    也可针对特定队列或用户单独配置(如通过 PartitionEpilog 或 UserEpilog)
  • 脚本核心逻辑(以 Bash + psql 为例):
    #!/bin/bash
    # 获取作业环境变量
    JOB_ID=$SLURM_JOB_ID
    USER=$SLURM_JOB_USER
    STDOUT_PATH=$SLURM_STDOUT
    STDERR_PATH=$SLURM_STDERR
    
    # 读取输出文件内容(转义特殊字符适配SQL语法)
    STDOUT_CONTENT=$(cat "$STDOUT_PATH" | sed -e 's/\\/\\\\/g' -e "s/'/\\'/g")
    STDERR_CONTENT=$(cat "$STDERR_PATH" | sed -e 's/\\/\\\\/g' -e "s/'/\\'/g")
    
    # 连接PostgreSQL插入数据
    psql -h <数据库节点IP> -U <数据库用户> -d <目标数据库> -c "
    INSERT INTO slurm_job_outputs (job_id, username, stdout, stderr)
    VALUES ($JOB_ID, '$USER', '$STDOUT_CONTENT', '$STDERR_CONTENT')
    ON CONFLICT (job_id) DO UPDATE SET stdout = EXCLUDED.stdout, stderr = EXCLUDED.stderr;
    "
    
  • 预先在 PostgreSQL 中创建存储表:
    CREATE TABLE slurm_job_outputs (
        job_id BIGINT PRIMARY KEY,
        username VARCHAR(64) NOT NULL,
        stdout TEXT,
        stderr TEXT,
        finish_time TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
    );
    
  • 注意事项:需确保计算节点能访问 PostgreSQL 服务器,且执行脚本的 slurm 用户拥有数据库的插入权限(可通过 pg_hba.conf 配置信任计算节点IP段)。

2. 共享存储+定时同步方案

若集群已配置共享存储(如 NFS),可先统一作业输出路径,再通过定时任务同步到数据库:

  • 在 slurm.conf 中设置全局默认输出路径:
    DefaultStdout=/shared/slurm_output/%j.out
    DefaultStderr=/shared/slurm_output/%j.err
    
  • 编写定时脚本(通过 cron 按周期执行),扫描共享存储中的输出文件,将内容插入数据库后可选择归档或删除源文件:
    #!/bin/bash
    OUTPUT_DIR="/shared/slurm_output"
    ARCHIVE_DIR="${OUTPUT_DIR}/archived"
    mkdir -p "$ARCHIVE_DIR"
    
    for FILE in $OUTPUT_DIR/*.out; do
        JOB_ID=$(basename "$FILE" .out)
        # 检查是否已存入数据库
        EXISTS=$(psql -h <数据库节点IP> -U <用户> -d <库> -t -c "SELECT 1 FROM slurm_job_outputs WHERE job_id = $JOB_ID;")
        if [ -z "$EXISTS" ]; then
            STDOUT_CONTENT=$(cat "$FILE" | sed -e 's/\\/\\\\/g' -e "s/'/\\'/g")
            STDERR_CONTENT=$(cat "${OUTPUT_DIR}/${JOB_ID}.err" | sed -e 's/\\/\\\\/g' -e "s/'/\\'/g")
            # 从slurmdbd的记账表中获取用户名
            USERNAME=$(psql -h <数据库节点IP> -U <用户> -d <slurm记账库> -t -c "SELECT user_name FROM sacct_job WHERE job_id = $JOB_ID;" | xargs)
            
            psql -h <数据库节点IP> -U <用户> -d <目标库> -c "
            INSERT INTO slurm_job_outputs (job_id, username, stdout, stderr)
            VALUES ($JOB_ID, '$USERNAME', '$STDOUT_CONTENT', '$STDERR_CONTENT');
            "
            # 归档文件
            mv "$FILE" "$ARCHIVE_DIR/"
            mv "${OUTPUT_DIR}/${JOB_ID}.err" "$ARCHIVE_DIR/"
        fi
    done
    
  • 优势:分散计算节点的数据库访问压力,适合作业量较大的集群。

3. 自定义Slurm插件(进阶方案)

若需要深度集成,可基于 Slurm 插件开发框架,编写作业结束阶段的插件,直接捕获输出并写入数据库。此方案需要熟悉 Slurm 源码和插件开发规范,适合具备开发能力的团队。

三、关键注意事项

  • 若作业输出文件过大(超过1GB),PostgreSQL 的 TEXT 类型可能无法存储,可改用 BYTEA 类型存储二进制内容,或仅存储文件哈希值+文件路径到数据库,实际文件存储到对象存储(如 MinIO)中。
  • 需制定数据库数据清理策略,定期归档或删除老旧的作业输出数据,避免存储空间溢出。
  • 确保数据库节点的高可用性,可配置 PostgreSQL 主从复制,避免单点故障影响作业输出存储。

内容的提问来源于stack exchange,提问作者paul runner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:35:33