2. 安装与配置:Nextflow 安装,DSL2 语法简介,基础配置

工欲善其事,必先利其器。这一章我们先把 Nextflow 的环境搭好,顺便把 DSL2 的基本语法和常用配置捋一遍。这些基础不牢,后面版本控制和结果一致性就无从谈起。

2.1 Nextflow 安装:其实比你想象的简单

Nextflow 本质上是个 Java 应用,所以依赖 JDK(Java Development Kit)。我个人习惯用 OpenJDK 11 或 17,后者更稳。

检查 Java 环境
java -version
# 输出类似:openjdk version "17.0.9" 2023-10-17 LTS

确保 JDK ≥ 11 后,安装 Nextflow 只需要一行命令。我建议用官方推荐的 curl 方式:

curl -s https://get.nextflow.io | bash
chmod +x nextflow
# 然后把 nextflow 放到 PATH 里,比如:
sudo mv nextflow /usr/local/bin/

为啥不用包管理器?我在项目中试过用 conda 装,版本经常落后一两个小版本,而且有时候依赖冲突很头疼。直接 curl 拿到的就是最新稳定版,干净利落。

装完之后验证一下:

nextflow -version

N E X T F L O W
version 24.04.2 build 5901
lastModified 2024-05-30 12:34:56 UTC
...

看到版本号就说明成了。嗯,这里有个坑:如果你在 macOS 上遇到 Permission denied,别忘了 chmod +x,我第一次装就忘了这步,还以为是 Java 版本问题。

2.2 DSL2 语法简介:核心概念一目了然

从 Nextflow 21.04 开始,DSL2 成了默认。说白了,DSL2 就是把流程拆成更小的模块化组件。你想想看,以前写流水线跟写大长脚本似的,现在每个步骤可以独立定义、复用。

重点记住三个东西:process、channel、workflow。

概念作用我的一句话总结
process定义每个计算步骤(命令+输入输出)流水线上的一个工位
channel数据管道,连接 process 的输入输出传送带,负责把物料(文件/值)递过去
workflow编排 process 的执行顺序和依赖生产经理,决定谁先干活、谁后干活

举个最简单的例子。你想对一个文件做两次处理:先过滤,再统计。用 DSL2 写出来大概长这样:

// my_pipeline.nf
nextflow.enable.dsl=2

process FILTER {
    input:
    path input_file

    output:
    path "filtered.txt"

    script:
    """
    grep 'some_pattern' $input_file > filtered.txt
    """
}

process COUNT {
    input:
    path input_file

    output:
    stdout

    script:
    """
    wc -l $input_file
    """
}

workflow {
    FILTER( channel.fromPath("data.txt") )
    COUNT( FILTER.out )
    COUNT.out.view { "行数: $it" }
}

你看,每个 process 只管自己的事,workflow 里用 FILTER.out 把过滤结果传给 COUNT。这就是模块化。我去年重构一个老项目时,发现原来的流水线全写在一个大 process 里,迁移到 DSL2 后每个步骤独立测试,爽多了。

DSL2 的另一大好处:
  • 支持 process 的 fromStateChannel 等新功能,方便做分支和合并
  • 可以在 workflow 里直接写条件判断和循环,不用再绕弯子

2.3 基础配置:nextflow.config 该放什么

一台机器上跑 Nextflow 没问题,但到了集群或云环境,配置必须统一。不然你本地能跑,别人机器上就报错——这还谈什么结果一致性?

我的习惯是把公共配置写到一个 nextflow.config 文件里,放在流水线根目录。典型内容:

params {
    input = ""
    outdir = "./results"
    genome = "GRCh38"
}

process {
    executor = 'local'
    cpus = 2
    memory = '4 GB'
}

docker {
    enabled = true
    runOptions = '-u $(id -u):$(id -g)'
}

manifest {
    name = 'my-nf-pipeline'
    version = '1.0.0'
    nextflowVersion = '>=24.04.0'
}

timeline {
    enabled = true
}
report {
    enabled = true
}
trace {
    enabled = true
}

这里面有几个关键点我挨个说一下。

  • params:定义用户输入参数的默认值。别人调用你流水线时如果不传 --input,就会用这个默认值。我在项目里见过有人直接把硬编码路径写到 process 里,结果换数据源就改脚本,太坑了。
  • process.executor:分布式的精髓。本地测试用 local,上集群换成 slurm、pbs 或 awsbatch。配置一改,不需要动一句脚本。
  • docker.enabled:保证环境一致性最粗暴也最有效的方法。我强烈建议开启,配合 Docker/Singularity 镜像,你的流水线就能在任何机器上复现相同结果。
  • manifest:记录流水线版本和 Nextflow 最低版本要求,这对版本控制非常重要。
  • timeline/report/trace:调试和审计三大件,开起来不亏。
曾经踩过的坑
我把 Docker 默认的 runOptions 写成 --rm,结果在 SLURM 集群上容器跑完自动销毁,日志全丢。后来加了 runOptions = '-u $(id -u):$(id -g)' 避免权限问题,还手动设置了 workDir 持久化。记住,Docker 选项在不同执行环境下行为可能不一样,一定要在目标环境上先跑个小例子验证。

2.4 知识体系一图览

下面这张图把本章三个模块的关系理清了。你先装好 Nextflow,然后学会 DSL2 的 process + channel + workflow 三要素,最后通过 nextflow.config 把执行环境、资源、容器、版本号统一起来。只有这三个环节都到位了,后面的版本控制和结果一致性才有基石。

Nextflow 安装与配置知识体系 安装 Nextflow JDK ≥ 11 curl 安装 → 加入 PATH DSL2 语法 process(计算步骤) channel(数据管道) workflow(流程编排) 基础配置(nextflow.config) params(默认参数) | process(执行器/资源) docker(环境一致) | manifest(版本控制) timeline/report/trace(可重现性审计) 三者齐备 → 版本控制与结果一致性的基础

2.5 小练习:验证你的安装和配置

光看不练等于白学。我建议你现在就跑一次官方 Hello 示例,确认环境没问题:

nextflow run hello

N E X T F L O W  ~  version 24.04.2
executor >  local (4)
[74/...] process > sayHello (1)
[75/...] process > sayHello (2)
[76/...] process > sayHello (3)
[77/...] process > sayHello (4)
...

看到 4 个进程成功跑过,恭喜你,Nextflow 已经能正常工作了。接下来我们再创建一个最简单的 nextflow.config,放你刚才看的几个关键字段(params、manifest、docker.enabled),然后重新跑一次 Hello。对比两次运行结果,你会发现即使加了配置,输出完全一样。这就是结果一致性的第一课:配置不影响核心逻辑,只控制执行环境。

我的建议
开局就把配置模板写好,后面每个新项目直接复制修改。宁可在配置里多写几行注释,也别留空。我见过有人把 params.outdir 写成 params.out,结果传参时死活不生效,排查半天——规范命名能省你很多时间。