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

使用SGE+Apptainer运行Nextflow工作流时出现bwa命令未找到错误

Nextflow + SGE + Apptainer 运行报错:bwa: command not found

问题详情

执行命令nextflow run main.nf -profile sge,apptainer运行工作流时,出现bwa: command not found错误。但手动执行apptainer run workflow.sif进入容器后,确认bwa及其他工具已正常安装,Nextflow无法找到工具的原因不明。

相关配置文件

Apptainer构建文件

Bootstrap: docker
From: rocker/r-ubuntu:22.04

%post
# automake
apt-get update \\
    && apt-get install -y --no-install-recommends build-essential automake bzip2 wget unzip \\
    python3 python3-dev python3-pip python3-venv git git-lfs default-jdk ant \\
    libbz2-dev libsdl1.2-dev liblzma-dev libcurl4-openssl-dev zlib1g-dev libxml2-dev \\
    r-cran-tidyverse bwa samtools multiqc datamash && rm -rf /var/lib/apt/lists/*

# CONDA 
%environment
    export LC_ALL=C
    export LC_NUMERIC=en_GB.UTF-8
    export PATH="/opt/miniconda/bin:$PATH"
%post
    #essential stuff but minimal
    apt update
    #for security fixe:
    #apt upgrade -y
    apt install -y wget bzip2
    #install conda
    cd /opt
    rm -fr miniconda
    #miniconda3: get miniconda3 version 4.7.12
    wget https://repo.continuum.io/miniconda/Miniconda3-4.7.12-Linux-x86_64.sh -O miniconda.sh
    #install conda
    bash miniconda.sh -b -p /opt/miniconda
    export PATH="/opt/miniconda/bin:$PATH"
    #add channels
    conda config --add channels defaults
    conda config --add channels bioconda
    conda config --add channels conda-forge
    #install trimmomatic
    conda install -y -c conda-forge -c bioconda nextflow
    conda install -y -c conda-forge -c bioconda trimmomatic
    conda install -y -c conda-forge -c bioconda gatk4
    conda install -y -c conda-forge -c bioconda fastqc
    #cleanup
    conda clean -y --all
    rm -f /opt/miniconda.sh
    apt autoremove --purge
    apt clean

# RSTUDIO
mkdir -p /usr/local/lib/R/etc/ /usr/lib/R/etc/
echo "options(repos = c(CRAN = 'https://cran.rstudio.com/'), download.file.method = 'libcurl', Ncpus = 4)" | tee /usr/local/lib/R/etc/Rprofile.site | tee /usr/lib/R/etc/Rprofile.site
R -e 'install.packages("remotes")'
# Update apt-get
Rscript -e 'install.packages("remotes", version = "2.4.2")'
Rscript -e 'remotes::install_cran("rmarkdown",upgrade="never", version = "2.19")'
Rscript -e 'remotes::install_cran("knitr",upgrade="never", version = "1.41")'
Rscript -e 'remotes::install_cran("tidyverse",upgrade="never", version = "1.3.2")'
Rscript -e 'remotes::install_cran("plotly",upgrade="never", version = "4.10.1")'
Rscript -e 'remotes::install_cran("RColorBrewer",upgrade="never", version = "1.1-3")'
Rscript -e 'remotes::install_cran("data.table",upgrade="never", version = "1.14.6")'
Rscript -e 'remotes::install_cran("viridis",upgrade="never", version = "0.6.2")'
Rscript -e 'remotes::install_cran("DT",upgrade="never", version = "0.26")'

%runscript
exec /bin/bash "$@"
%startscript
exec /bin/bash "$@"

nextflow.config配置

params {
    ...

    max_memory      = 10.GB       
    max_cpus        = 4    
    max_time        = '48.h'         
}

process {
    withLabel: big_mem {
        cpus = "${params.max_cpus}"
        memory = "${params.max_memory}"
        time = "${params.max_time}"
        penv = 'smp' 
    }
}

profiles {
    conda {
        conda.enabled = true
        docker.enabled = false
        apptainer.enabled = false
        process.conda = "./envs/env.yml"
    }
    mamba {
        conda.enabled       = true
        conda.useMamba      = true
        docker.enabled      = false
        apptainer.enabled   = false
    }
    docker {
        conda.enabled           = false
        docker.enabled          = true
        docker.userEmulation    = true
        apptainer.enabled       = false
        process.container       = "directory/myworkflow:latest"
    }
    apptainer {
        conda.enabled           = false
        apptainer.enabled       = true
        apptainer.autoMounts    = true
        docker.enabled          = false
        process.container       = 'file://myworkflow.sif'
    }
    sge {
        process {
            executor        = "sge"
            scratch         = true
            stageInMode     = "copy"
            stageOutMode    = "move"
            errorStrategy   = "retry"
            clusterOptions = '-S /bin/bash -o job.log -e job.err'
        }
        executor {
            queueSize = 1000
        }
    } 

}

manifest {
    name            = 'directory/myworkflow'
    homePage        = 'https://github.com/directory/myworkflow'
    description     = 'analysis pipeline'
    mainScript      = 'main.nf'
    nextflowVersion = '!>=22.10.0'
    version         = '1.1.0'
}

env {
    PYTHONNOUSERSITE = 1
    R_PROFILE_USER   = "/.Rprofile"
    R_ENVIRON_USER   = "/.Renviron"
}

// keep trace
trace {
    enabled = true
    file = "${params.outdir}/trace.txt"
    overwrite = true
}

// keep report
report {
    enabled = true
    file = "${params.outdir}/report.html"
    overwrite = true
}

// Function to ensure that resource requirements don't go beyond
// a maximum limit
def check_max(obj, type) {
    if (type == 'memory') {
        try {
            if (obj.compareTo(params.max_memory as nextflow.util.MemoryUnit) == 1)
                return params.max_memory as nextflow.util.MemoryUnit
            else
                return obj
        } catch (all) {
            println "   ### ERROR ###   Max memory '${params.max_memory}' is not valid! Using default value: $obj"
            return obj
        }
    } else if (type == 'time') {
        try {
            if (obj.compareTo(params.max_time as nextflow.util.Duration) == 1)
                return params.max_time as nextflow.util.Duration
            else
                return obj
        } catch (all) {
            println "   ### ERROR ###   Max time '${params.max_time}' is not valid! Using default value: $obj"
            return obj
        }
    } else if (type == 'cpus') {
        try {
            return Math.min( obj, params.max_cpus as int )
        } catch (all) {
            println "   ### ERROR ###   Max cpus '${params.max_cpus}' is not valid! Using default value: $obj"
            return obj
        }
    }
}

解决方案

1. 确保容器环境变量在非交互式shell中生效

Nextflow调用Apptainer时默认使用非交互式exec模式,%environment块中定义的变量可能不会自动加载。需要将环境变量写入系统profile:

修改Apptainer文件的%post块,在conda安装完成后添加:

%post
# (保留原post内容)
# 将环境变量写入profile,确保非交互式shell加载
echo 'export LC_ALL=C' >> /etc/profile.d/workflow_env.sh
echo 'export LC_NUMERIC=en_GB.UTF-8' >> /etc/profile.d/workflow_env.sh
echo 'export PATH="/opt/miniconda/bin:$PATH"' >> /etc/profile.d/workflow_env.sh

重新构建容器:apptainer build workflow.sif Apptainer

2. 调整Nextflow的Apptainer挂载设置

apptainer.autoMounts = true可能导致宿主系统PATH覆盖容器内路径,建议关闭自动挂载并显式绑定必要目录:

修改nextflow.config的apptainer profile:

apptainer {
    conda.enabled           = false
    apptainer.enabled       = true
    apptainer.autoMounts    = false
    apptainer.bind          = ["/path/to/your/workspace"]  # 替换为你的工作目录
    docker.enabled          = false
    process.container       = 'file://myworkflow.sif'
}

3. 强制SGE加载shell profile

SGE的非交互式bash默认不加载profile,可在clusterOptions中添加-l参数强制加载登录shell:

修改nextflow.config的sge profile:

sge {
    process {
        executor        = "sge"
        scratch         = true
        stageInMode     = "copy"
        stageOutMode    = "move"
        errorStrategy   = "retry"
        clusterOptions = '-S /bin/bash -l -o job.log -e job.err'
    }
    executor {
        queueSize = 1000
    }
}

4. 验证工具路径并直接调用

在容器内执行which bwa获取绝对路径(例如/usr/bin/bwa),在Nextflow的process脚本中直接使用绝对路径调用工具,或者确认该路径在容器的PATH中。

内容的提问来源于stack exchange,提问作者1288Meow

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 13:12:02