2. 安装与配置:Nextflow 安装,DSL2 语法简介,基础配置
工欲善其事,必先利其器。这一章我们先把 Nextflow 的环境搭好,顺便把 DSL2 的基本语法和常用配置捋一遍。这些基础不牢,后面版本控制和结果一致性就无从谈起。
2.1 Nextflow 安装:其实比你想象的简单
Nextflow 本质上是个 Java 应用,所以依赖 JDK(Java Development Kit)。我个人习惯用 OpenJDK 11 或 17,后者更稳。
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 后每个步骤独立测试,爽多了。
- 支持 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 把执行环境、资源、容器、版本号统一起来。只有这三个环节都到位了,后面的版本控制和结果一致性才有基石。
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,结果传参时死活不生效,排查半天——规范命名能省你很多时间。