Nextflow安装和使用

Nextflow install and Setting

高通量测序分析的流程引擎:Nextflow 安装与快速入门,顺带了解 nf-core 生态与容器化运行

“Dataflow variables are spectacularly expressive in concurrent programming”

Nextflow的核心思想: 将并发编程中的“同步”与“数据传递”合二为一,通过“赋值即同步”的语义,从根本上消除了传统共享内存并发中的竞态条件和显式锁机制

Nextflow 是一个用于构建可扩展、可移植且可复现工作流的流程管理系统。它采用数据流编程模型,通过让你专注于数据流转与计算过程,简化了并行及分布式流水线的编写。Nextflow 能够将工作流部署到多种执行平台上,包括本地机器、高性能计算(HPC)调度器以及云端环境。此外,Nextflow 支持多种计算环境、软件容器运行时及包管理器,使工作流能够在可复现且隔离的环境中运行

1. 背景

Nextflow 语言的设计灵感源自 Unix 哲学,即通过将众多简单的命令行工具组合起来,构建出功能强大的工作流。同理,Nextflow 脚本也是由许多简单的“进程”组合成流水线。每个进程可以使用任何受支持的编程语言来执行指定的工具或脚本,你只需定义好进程的输入和输出,Nextflow 就会自动为你协调各个任务的执行

Unix philosophy:Unix 哲学,指“让每个程序只做好一件事”的设计思想,强调通过组合简单工具来解决复杂问题

1.1 诞生发展历史

2013年3月,Nextflow 在 GitHub 首次发布,由西班牙巴塞罗那基因组调控中心(CRG)的工程师 Paolo Di Tommaso 主导开发。其诞生直接受 Docker 容器技术启发——Di Tommaso 在观看 Docker 创始人 Solomon Hykes 的演讲后,认定容器是解决科学工作流”可复现性”问题的关键,因此从设计之初就将 Docker 作为”一等公民”,核心目标是让数据密集型工作流能在任何基础设施上运行。

技术底座与早期版本

  • 语言与架构:基于 JVM 运行,采用 Groovy 语言编写,核心设计遵循 Unix 哲学与数据流编程模型,通过”进程(process)“和”通道(channel)“的组合实现并行与分布式计算

  • 执行平台支持:早期即支持本地、HPC 调度器(如 Slurm)、云平台(AWS、GCP)等多种执行环境,奠定了”一次编写,随处运行”的基础

关键版本迭代

  • 2021-2022年:DSL2 成为默认语法:DSL2(领域特定语言第二版)是 Nextflow 的重大里程碑,它将工作流拆解为可复用的”模块(modules)“和”子流程(subworkflows)“,类似”乐高积木”式的模块化设计。2022年4月发布的 22.04.0 稳定版正式将 DSL2 设为默认语法,同时要求 Java 11 及以上版本,引入了现代 Java 运行时能力

  • 2023年:日历化版本管理:采用”年.月.补丁”的日历版本格式(如 23.10.1),每年4月和10月发布稳定版,每月发布 edge 版(含实验性功能)

  • 2024-2025年:语言服务器与插件生态:2024.10 版本引入语言服务器,2025.04 版本集成语法解析器,2025.10 版本新增静态类型、工作流输入输出声明、nextflow auth/nextflow launch 新命令,并推出官方插件注册中心(Plugin Registry),简化插件发现与管理

1.2 社区生态

2018年,nf-core 社区成立,旨在创建和维护一个由社区共同策划的高质量生物信息学分析流程集合。其核心贡献包括

  • 标准化流程:截至2025年2月,已发布124个标准化流程,涵盖基因组学、转录组学、质谱、显微成像等领域,甚至扩展到天体物理学、地球科学等非生物领域

  • 模块库:基于 DSL2 的模块化设计,nf-core/modules 积累了超过1400个模块和80个子流程,研究者可直接调用这些经过社区验证的标准化组件

注记

DSL2(Domain-Specific Language 2)是 Nextflow 的领域特定语言第二版,引入了模块化工作流定义范式,将流程逻辑、执行配置、输入输出契约完全解耦

  • 模块(module):是 DSL2 的最小复用单元,对应一个独立的计算任务, 每个模块都封装了完整的输入输出定义、执行脚本、资源约束(CPU/内存)、容器环境声明,甚至可以关联独立的测试用例和元数据说明

  • 子流程(subworkflow):是多个模块的有序编排组合,对应一个完整的功能片段(比如“原始测序数据质控+接头修剪”的完整预处理流程),可以直接被其他流程调用,避免重复编写相同的步骤组合

  • 工作流(workflow):是最终的分析流水线,通过调用模块或子流程,配合 Channel 数据流机制,完成从原始数据输入到最终结果输出的全流程调度

2. 核心模块

2.1 通道

核心是:process,workflow,channel

英文 推荐译法 说明
Processes 进程 Nextflow 中的基本计算单元,每个进程封装一个独立的计算步骤(如质控、比对等),彼此隔离、独立执行。
Dataflow 数据流 / 数据流转 指数据在进程之间流动的方式。Nextflow 采用数据流编程模型,进程之间通过异步的通道(Channel)传递数据,数据到达即触发下游进程执行。

一个进程可以定义一个或多个输入和输出。数据通过异步的数据流结构在进程之间流动,这些结构被称为通道(Channel)和值(Value)。这些进程之间的数据依赖关系隐式地决定了执行流程

核心理解是在通道上:通道相当于一辆车,放着等待处理的数据

  • Channels(通道):Nextflow 中用于在进程间传递数据的核心异步数据结构,类似“数据管道”,支持队列通道(Queue Channel)和值通道(Value Channel)两种类型

  • 核心异步数据结构指的是用于在进程(Process)之间传递数据、实现数据流编程模型的两种结构:通道(Channel)和值(Value)

特性 队列通道(Queue Channel) 值通道(Value Channel)
数据项数量 多个 单个
是否可重复读取 否(读取即消耗) 是(无限次读取)
典型用途 传递多个样本/文件 传递参考文件/配置参数
创建方式 Channel.of()Channel.fromPath()、进程输出 Channel.value()、隐式包装、聚合操作符

队列通道 就像一条传送带:物品从一端放上去,另一端的人取走一个就少一个,取完即止

值通道 就像一块公告板:上面贴着一张通知,所有人都可以反复查看,内容不会消失.

// 1. 工厂方法创建通道,装入3个样本名
samples_ch = Channel.of('sample1', 'sample2', 'sample3')

// 2. 定义进程,从通道取数据
process fastqc {
    input:
    val sample from samples_ch    // 从通道取数据
    output:
    path "${sample}_fastqc.html"  // 输出放入新通道
    script:
    """
    fastqc ${sample}.fastq
    """
}

唯一需要手动创建通道的场景:数据从”外部世界”进入 Nextflow 流水线的那一刻,一旦数据已经进入流水线,后续所有通道的创建都是自动的,你只需要”连接”它们。

数据源 工厂方法 示例
单个/多个文件路径 Channel.fromPath() Channel.fromPath('/data/*.fa')
配对文件(如双端测序) Channel.fromFilePairs() Channel.fromFilePairs('/data/*_{1,2}.fq')
内存中的列表/值 Channel.of() Channel.of(1, 2, 3)
单个值(不消耗) Channel.value() Channel.value(params.db)
NCBI SRA 数据 Channel.fromSRA() Channel.fromSRA('SRR123456')
空通道 Channel.empty() Channel.empty()
监控文件夹新文件 Channel.watchPath() Channel.watchPath('/data/*.fa')

通道创建的规则就一条:数据从”流水线外部”进入时,你手动创建;数据在”流水线内部”流转时,Nextflow 自动创建。你只需要关心”数据从哪来、要到哪去”,中间的通道 Nextflow 会帮你打理好。

2.2 Process 进程

这段代码是一个非常经典的 Nextflow 入门示例,展示了一个完整的 BLAST 搜索 → 提取序列 的两步流水线

部分 作用
params 定义脚本参数(全局变量),支持命令行覆盖
process 定义计算任务(流水线中的每个”步骤”)
workflow 定义数据流,将多个 process 串联起来
// Script parameters
params.query = "/some/data/sample.fa"
params.db = "/some/path/pdb"

// Define the blast_search process
process blast_search {
  input:
  path query
  path db

  output:
  path "top_hits.txt"

  script:
  """
  blastp -db $db -query $query -outfmt 6 > blast_result
  cat blast_result | head -n 10 | cut -f 2 > top_hits.txt
  """
}

// Define the extract_top_hits process
process extract_top_hits {
  input:
  path top_hits
  path db

  output:
  path "sequences.txt"

  script:
  """
  blastdbcmd -db $db -entry_batch $top_hits > sequences.txt
  """
}

// Define the workflow
workflow {
  def query_ch = channel.fromPath(params.query)
  blast_search(query_ch, params.db)
  extract_top_hits(blast_search.out, params.db).view()
}
  1. 脚本参数(params)
params.query = "/some/data/sample.fa"
params.db = "/some/path/pdb"
  • params 是 Nextflow 内置的全局变量对象,用于定义可在命令行覆盖的参数
  • 运行时可以用 --query /path/to/file.fa 覆盖默认值
  • 在 workflow 块和 process 的 script 中都可以直接引用 params.query

2.第一个 process:blast_search

process blast_search {
  input:
  path query
  path db

  output:
  path "top_hits.txt"

  script:
  """
  blastp -db $db -query $query -outfmt 6 > blast_result
  cat blast_result | head -n 10 | cut -f 2 > top_hits.txt
  """
}
  1. input 块 —— 声明输入
  • 声明了两个输入:query(查询序列文件)和 db(BLAST 数据库路径)
  • path 是输入限定符(qualifier),告诉 Nextflow 这两个输入是文件/目录路径,Nextflow 会自动处理文件的暂存(staging)——把文件拷贝到任务的 work/ 目录中
提示

path 限定符(qualifier)是 Nextflow 中专门用于声明”文件/目录路径类型数据”的输入或输出限定符,它的核心作用是告诉 Nextflow:“这个变量不是一个普通字符串,而是一个需要特殊处理的文件路径”,从而触发 Nextflow 的文件暂存(staging)机制

  • 在 workflow 块中调用 blast_search(query_ch, params.db) 时,query_ch 是一个通道,params.db 是一个简单字符串。Nextflow 会自动把 params.db 包装成值通道,所以两个输入都能正确传递
  1. output块–声明输出
  • 声明该进程会生成一个名为 top_hits.txt 的文件
  • Nextflow 会在进程执行结束后,自动把 top_hits.txt 放入一个新的队列通道中,供下游进程消费
  • 在 workflow 中可以通过 blast_search.out 来引用这个输出通道
  1. script块–执行命令
  • 使用三引号 """ 包裹多行 Bash 脚本
  • $db$query 是 Groovy 变量插值,Nextflow 会把 input 中声明的变量值替换进来

Process的完整语法模板

process <名称> {
  [directives]    // 指令(可选):如 cpus, memory, container, publishDir 等
  input:          // 输入声明(可选)
    <限定符> <变量名>
  output:         // 输出声明(可选)
    <限定符> <文件名>
  when:           // 条件判断(可选)
    <布尔表达式>
  script:         // 执行脚本(必需,或用 exec 块写 Groovy 代码)
    """
    <Bash 命令>
    """
}
限定符 含义
val 传递一个简单值(字符串、数字等)
path 传递文件或目录路径
tuple 传递多个值的组合(如样本名+文件对)
each 对列表中的每个元素分别执行一次
  • Process 是并行执行的:如果输入通道中有 N 个数据项,process 会自动触发 N 次独立的任务执行,天然实现并行
  • 每个 process 在独立的 work 目录中运行:Nextflow 会为每个任务创建一个唯一的 work// 目录,输入文件被软链接或拷贝进去,输出文件从该目录收集。这保证了任务之间的隔离性
  • 断点续传(-resume):如果流程中断,加上 -resume 参数重新运行,Nextflow 会跳过已成功完成的任务,从断点继续执行,大幅节省时间

Directives(指令)是写在 process 内部、位于 input 之前的“任务配置项”,用于定义该任务的运行环境、资源需求、输出位置及容错策略

process my_task {
    // ✅ 指令区:必须放在最上面
    cpus 4
    memory '16 GB'
    container 'biocontainers/samtools:1.3.1'
    publishDir params.outdir

    // 其他声明块
    input:
    path reads
    ...
}

2.3 workflow 块 —— 串联流程

workflow {
  def query_ch = channel.fromPath(params.query)
  blast_search(query_ch, params.db)
  extract_top_hits(blast_search.out, params.db).view()
}
  1. 创建输入通道 def query_ch = channel.fromPath(params.query)是通道工厂方法,根据文件路径创建一个队列通道,通道中装着匹配的文件路径对象

  2. 调用第一个进程,像调用函数一样调用 process,按顺序传入输入通道,query_ch 是队列通道,params.db 是简单值(被隐式包装为值通道)

2.4 执行器

  • Process(进程):定义”做什么”——要执行什么命令或脚本(比如 bwa mem、samtools sort)

  • Executor(执行器):定义”怎么跑、跑在哪”——这个脚本是直接在本地跑,还是提交到集群的某个队列里跑。

如果你什么都不配置,Nextflow 默认使用 local executor,也就是在你启动 Nextflow 的那台机器上直接运行所有任务。这非常适合开发和测试阶段——写代码、调逻辑、验证流程,直接在笔记本或工作站上就能跑

Nextflow真正强大的特性–执行抽象层

你只需要写一次流程代码(main.nf),然后通过修改配置文件(nextflow.config)中的 executor 设置,就可以无缝切换到不同的运行平台

// 本地运行(默认)
process.executor = 'local'

// 提交到 Slurm 集群
process.executor = 'slurm'

// 提交到 AWS 云端
process.executor = 'awsbatch'

3. Nextflow安装

Nextflow兼容所有的Linux发行版(Ubuntu、CentOS 等)和 macOS, Windows用户需要通过 WSL2(Windows Subsystem for Linux) 来运行。简单来说,就是在 Windows 里装一个 Linux 子系统,Nextflow 跑在这个子系统里

3.1 Java安装

Nextflow 要求 Java 17 以上,核心原因是 Nextflow 本身是用 Groovy 编写的,而 Groovy 运行在 JVM 上;从 Nextflow 22.10 版本开始,官方将最低运行时要求提升到了 Java 17

# 查看java版本
java --version

最推荐的方式是使用SDKMAN,可以方便的管理多个java版本

# 安装 SDKMAN
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"

# 安装 Java 17 LTS(Temurin 发行版,推荐)
sdk install java 17.0.10-tem

# 验证
java -version
# 输出: openjdk version "17.0.10" ...

当然也可使用系统包管理器

# Ubuntu/Debian
sudo apt install openjdk-20-jre

# CentOS/RHEL
sudo yum install java-20-openjdk

# macOS (Homebrew)
brew install openjdk@20

3.2 安装Nextflow

Nextflow 提供了多种安装途径,你可以根据自己的环境和使用习惯选择最合适的一种

方式 命令 优点 缺点 适用场景
自安装包(Self-installing package) curl -s https://get.nextflow.io \| bash 一键安装、支持 self-update 自动升级、维护最省心 需要联网 绝大多数用户的首选
Conda 安装 conda install -c bioconda nextflow 与 Conda 环境统一管理、版本可控 版本可能滞后、偶尔有依赖冲突 已用 Conda 管理生信工具的用户
独立发行版(Standalone distribution) 下载 nextflow-xx-dist 文件直接运行 无需联网、适合离线部署 需手动下载、手动更新 内网/离线服务器、需要定制化配置的场景
  1. 自安装包
# 下载并安装
curl -s https://get.nextflow.io | bash

# 赋予执行权限
chmod +x nextflow

# 移动到 PATH 目录
mkdir -p $HOME/.local/bin
mv nextflow $HOME/.local/bin/

# 确保 PATH 包含该目录(添加到 ~/.bashrc)
export PATH="$HOME/.local/bin:$PATH"
  1. Conda安装
# 创建专用环境
conda create --name nextflow-env bioconda::nextflow
conda activate nextflow-env

4. 学习第一个脚本

安装好之后,就可以运行nextflow --version检查是否能够运行,接着这一节学习如何

  • Running a pipeline:运行流程
  • Modifying and resuming a pipeline:修改并恢复流程运行
  • Configuring a pipeline parameter:配置流程参数

4.1 了解一个pipline

你将运行一个基础的 Nextflow 流程,该流程会将一段文本字符串拆分成两个文件,然后再将文件中的小写字母转换成大写字母

// Default parameter input
params.str = "Hello world!"

// split process
process split {
    publishDir "results/lower"

    input:
    val x

    output:
    path 'chunk_*'

    script:
    """
    printf '${x}' | split -b 6 - chunk_
    """
}

// convert_to_upper process
process convert_to_upper {
    tag "$y"

    input:
    path y

    output:
    path 'upper_*'

    script:
    """
    cat $y | tr '[a-z]' '[A-Z]' > upper_${y}
    """
}

// Workflow block
workflow {
    main:
    ch_str = channel.of(params.str)          // Create a channel using parameter input
    ch_chunks = split(ch_str)                // Split string into chunks and create a named channel
    ch_upper = convert_to_upper(ch_chunks.flatten()) // Convert lowercase letters to uppercase letters

    publish:
    lower = ch_chunks.flatten()
    upper = ch_upper
}

output {
    lower {
        path 'lower'
    }
    upper {
        path 'upper'
    }
}
  • params 是 Nextflow 内置的全局参数对象
  • 默认值为 "Hello world!",你可以在命令行通过 --str 覆盖它 nextflow run main.nf --str "自定义文本"

process split

  • publishDir "results/lower":将该 Process 的输出文件自动发布(复制/链接)到 results/lower 目录,方便后续查看结果
  • input: val x:接收一个值类型(字符串)
  • output: path 'chunk_*':输出所有以 chunk_ 开头的文件
  • split -b 6 - chunk_:Bash 命令,按每 6 字节切分,生成 chunk_aa、chunk_ab 等文件

process convert_to_upper

  • tag "$y":给每个任务打上标签(显示在终端日志中),方便调试时识别是哪个文件在处理
  • input: path y:接收上一步输出的文件路径
  • output: path 'upper_*’:输出所有以 upper_ 开头的文件

y是随手起的名称,可以换的

Workflow:数据流串联

main

  • channel.of(params.str):将字符串包装成 Channel
  • split(ch_str):调用 split Process,返回一个包含多个 chunk 文件的 Channel
  • ch_chunks.flatten():将 Channel 中的文件列表”展平”,使每个文件单独流向下游
  • convert_to_upper(...):调用 convert_to_upper Process,将每个 chunk 转为大写

publish: 声明哪些 Channel 的结果需要被发布到输出目录

  • lower = ch_chunks.flatten():将拆分后的 chunk 文件发布到 results/lower
  • upper = ch_upper:将转大写后的文件发布到 results/upper

Output 块:定义发布路径

  • lower { path 'lower' }:lower 对应的文件发布到 results/lower/
  • upper { path 'upper' }:upper 对应的文件发布到results/upper/

运行后的目录

results/
├── lower/
   ├── chunk_aa      # "Hello "(前6字节)
   └── chunk_ab      # "world!"(后6字节)
└── upper/
    ├── upper_chunk_aa  # "HELLO "
    └── upper_chunk_ab  # "WORLD!"

4.2 运行pipline

  1. 在自己想放的文件中,创建main.nf文件,把上述脚本放入文件中保存
  2. 在有main.nf文件夹中运行nextflow run main.nf
  3. 后续看到

 N E X T F L O W   ~  version 26.04.6

Launching `main.nf` [silly_fermi] revision: 55ca42d672

executor >  local (3)
[ae/949563] split (1)                   | 1 of 1 ✔
[97/71686b] convert_to_upper (chunk_aa) | 2 of 2 ✔

Outputs:

  /home/erwin/projectQiao/nextflow/results

  lower:
    - lower/chunk_aa
    - lower/chunk_ab

  upper:
    - upper/upper_chunk_aa
    - upper/upper_chunk_ab

Nextflow 会创建一个 work 工作目录来存放流程运行过程中产生的所有临时文件。流程中的每个 Process 会被拆分成一个或多个独立的 Task(任务) 来执行。在这个例子中,split 过程只执行了 1 个任务,而 convert_to_upper 过程因为接收到了两个 chunk 文件,所以执行了 2 个任务。终端里显示的类似 82/457482 这样的十六进制字符串,是一个唯一哈希值的前缀,用来标识每个任务对应的工作目录

4.3 修改pipline和resume

Nextflow 会在一个任务缓存(task cache)中记录所有任务的执行情况,这个缓存本质上是一个存储了历史任务记录的键值对数据库。任务缓存会和工作目录(work directory)配合使用,用来恢复那些已经跑过的任务。如果你修改了流程并加上 -resume 参数重新运行,Nextflow 只会重新执行那些被修改过的步骤;而对于没有发生变化的任务,它会直接复用之前缓存好的结果,完全不用重跑

  1. 打开main.nf
  2. 替换一个process
process convert_to_upper {
    tag "$y"

    input:
    path y

    output:
    path 'upper_*'

    script:
    """
    rev $y > upper_${y}
    """
}
  1. 保存之后,继续运行nextflow run main.nf -resume

5. 命令行操作模式

Nextflow也提供了强大的命令行控制方式

类型 标志格式 作用对象 用途 示例
Nextflow 选项(Options) 单破折号 - Nextflow 引擎本身 控制 Nextflow 的运行行为,如日志、工作目录、断点续跑等 -resume-log-profile-work-dir
Pipeline 参数(Parameters) 双破折号 -- 你的 Pipeline 脚本 传递数据给脚本中的 params.xxx 变量,如输入文件路径、输出目录等 --input--outdir--str