2  分析环境的搭建与必要的编程技术

本章提要

本章帮你把生信分析的工作台搭起来:本地负责写代码、绘图和运行 AI agent,重计算交给服务器。我们先比较 Windows、Linux 和 macOS 三种本地平台,完成 WSL 与 macOS 的基础配置;再打通与服务器的连接,学习文件传输、基本 Linux 命令与 Shell 脚本,并用 VS Code 远程开发;然后在服务器上用 apt 安装软件,用 conda 与 Bioconda 搭建生信环境;接着掌握 R 与 Python 的最低必要基础,读懂 YAML 与 JSON 配置;最后装好 Claude Code、Codex、ZCode 等 AI agent,并建立项目目录、版本管理与排错的基本习惯。

2.1 电脑、服务器与软件环境

选择并配置适合分析的本地工作环境。

生物信息学平台的构建

生物信息学的分析平台由本地电脑和远端服务器两部分组成。本地电脑主要用来编辑代码、用 R 等工具绘图,以及运行 Claude Code、Codex、ZCode 这类 AI coding agent 辅助编程;比对、定量这些消耗算力的计算,几乎都在远端服务器上完成。因此,配置本地环境时,顺手比追求性能更重要:选一个自己习惯的操作系统,把写代码、连接服务器和运行 AI agent 所需的环境配好。本章就从这张工作台开始,先配置本地系统,再学习连接服务器和基本操作。

Windows、Linux和macOS的选择

选择本地主机系统时,评判标准与挑选服务器不同。本地不承担重计算,我们主要考虑开发是否方便、与服务器环境有多接近,以及自己用得是否习惯。

Windows

Windows 生态最普及,但与 Linux 服务器差异较大:大多数开源生信软件只提供 Linux 版本的二进制包或源代码,在 Windows 上直接编译安装历来困难。WSL 的出现改变了这一点——在 Windows 上可以获得十分接近 Linux 命令行的操作和兼容性体验(见下一节)。对已经在使用 Windows 的读者,没有必要为了生信专门更换电脑,配置好 WSL 即可。

Linux

在本地直接使用 Linux 桌面(如 Ubuntu)的最大好处,是与服务器环境完全一致:同样的命令行、同样的软件安装方式,写好的脚本几乎可以原样搬上服务器。代价是日常办公和商业软件生态较弱,遇到问题需要一定的排查意愿。适合愿意把电脑完全当作开发工具使用的读者。

macOS

macOS 基于 Unix,自带终端和一批常用命令行工具,与 Linux 服务器天然接近,编译安装开源软件通常也顺利;同时保留了完整的图形界面生态,作为本地主机兼顾开发与日常使用。需要注意的是,苹果芯片(Apple Silicon)的 CPU 架构与多数服务器(x86_64)不同,个别只提供 x86 版本的软件需要通过系统自带的兼容层运行。

在 Windows 下使用 Linux 命令行

微软官方文档这样介绍 WSL(Windows Subsystem for Linux):

适用于 Linux 的 Windows 子系统可让开发人员按原样运行 GNU/Linux 环境 - 包括大多数命令行工具、实用工具和应用程序 - 且不会产生传统虚拟机或双启动设置开销。

安装WSL

在Windows 10(21H2及以后)和Windows 11上,以管理员权限启动PowerShell,一条命令就可以完成安装:

wsl --install

wsl --install会自动启用所需功能、下载Linux内核并默认安装Ubuntu,完成后按提示重新启动计算机。之后可以用wsl --list --online查看可安装的发行版,用wsl --install -d 发行版名称安装其他发行版。

在更旧的Windows 10版本上,wsl --install不可用,需要手动启用功能(以下小节作为旧方法保留)。以管理员权限启动PowerShell,依序执行以下两个命令后重新启动计算机。

启用“适用于 Linux 的 Windows 子系统”可选功能
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
启用“虚拟机平台”可选功能
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
设置WSL2为默认版本

使用wsl --install安装时默认已经是WSL2,通常无需这一步;只有在旧系统上手动启用功能后,才需要以管理员权限启动PowerShell执行以下命令,把之后安装的发行版默认设为WSL2。

wsl --set-default-version 2
安装发行版

访问Microsoft Store的Linux发行版页面,选择你想使用的发行版;在应用商店搜索 Linux,还可以找到更多选择。也可以按上一小节的方法,用 wsl --install -d 发行版名称 在命令行直接安装。

图 2.1: Microsoft Store 中的 Linux 发行版列表
创建账户和密码

发行版安装完成后,首次启动时会要求你创建用户名和密码。

图 2.2: Ubuntu 首次启动时的解包过程

Windows Terminal

Windows 终端可启用多个选项卡(在多个 Linux 命令行、Windows 命令提示符、PowerShell 和 Azure CLI 等之间快速切换)、创建键绑定(用于打开或关闭选项卡、复制粘贴等的快捷方式键)、使用搜索功能,以及使用自定义主题(配色方案、字体样式和大小、背景图像/模糊/透明度)。

在应用商店搜索Windows Terminal后安装即可。

图 2.3: Windows Terminal 中的多种终端会话

mac系统的基础配置

相比 Windows,macOS 的基础配置简单得多,通常不需要太多额外设置。系统自带的 Terminal 已经能完成绝大多数工作;习惯图形界面的读者也可以安装 iTerm2 等第三方终端,使用分页、分屏和搜索等增强功能。由于原生兼容 Unix,Linux 下的很多命令和工具在 macOS 上可以直接使用。需要安装命令行软件时,建议先装 Homebrew 包管理器,再用 brew install 安装。macOS 的劣势主要在少数商业软件和与服务器架构的差异上(见上一节),但作为本地主机,它仍是开箱即用程度最高的选择之一。

2.2 连接远端服务器

接下来,我们学习连接服务器、传输文件、执行命令,再用 VS Code 直接打开远端目录工作。如今的服务器几乎全部运行 Linux,常见的有 Ubuntu Server LTS、Debian,以及接替 CentOS 的 Rocky Linux 和 AlmaLinux。

使用ssh连接

SSH 是连接服务器的重要工具。Linux 和 macOS 都自带 ssh 命令;Windows 长期以来没有自带 SSH 命令,从 Windows 10 开始情况有所改善。较新的 Windows 10 和 Windows 11 已经预装 OpenSSH 客户端,在 PowerShell 中直接运行 ssh 即可。OpenSSH 服务器端仍需手动安装:在任务栏搜索“可选功能”,点击结果中的“添加可选功能”;也可以从“Windows设置→应用→可选功能”进入。

图 2.4: Windows 的可选功能管理页面

点击“添加功能”,选择需要的组件(例如“OpenSSH 服务器”;较早系统上未预装客户端时,也可在此安装“OpenSSH 客户端”),再点击“安装”,稍等即可完成。

连接服务器的基本命令是 ssh 用户名@服务器地址。下面用一个例子说明登录过程。

假设服务器地址是 192.168.1.100,你的用户名是 meng,连接时输入:

ssh meng@192.168.1.100

首次连接会提示确认主机指纹(fingerprint),输入 yes 回车后指纹会被保存,之后不会再询问。接着输入密码——屏幕上不显示任何字符是正常现象,输完直接回车。登录成功后,提示符会变成服务器上的样子,输入 exit 或按 Ctrl+D 即可退出返回本地。

每次都输密码既麻烦也不够安全,更推荐密钥登录。密钥成对存在:私钥留在本地,公钥放到服务器。用下面的命令生成一对密钥:

ssh-keygen -t ed25519

一路回车即可,密钥会保存在 ~/.ssh/ 目录下:id_ed25519 是私钥,id_ed25519.pub 是公钥。生成时可以设置一个私钥口令(passphrase),多一层保护;留空则使用时不需要再输口令。然后把公钥传到服务器上:

ssh-copy-id meng@192.168.1.100

这一次仍需要输入密码。之后再用 ssh 登录,服务器会用公钥验证你的身份,不再询问密码。要注意,私钥等于你在这台服务器上的钥匙,不要通过聊天工具或网盘发送,也不要提交进代码仓库。

如果经常连接多台服务器,可以为每台服务器起一个别名。编辑(没有就新建)本地家目录下的 ~/.ssh/config 文件:

Host lab
    HostName 192.168.1.100
    User meng
    Port 22
    IdentityFile ~/.ssh/id_ed25519

Host compute
    HostName 10.0.0.8
    User wangmeng

保存后,ssh lab 就等于 ssh meng@192.168.1.100,scp、rsync 和后面 VS Code 的远程连接也都能直接使用这些别名。服务器端口不是默认的 22 时,用 Port 指定;IdentityFile 在你有多对密钥时尤其有用。

文件的上传与下载

分析数据经常需要在本地与服务器之间往来:把原始数据传上去,把结果图表取回来。常用方式有两类:图形界面的 sftp 软件(如 FileZilla)适合零散文件的可视化拖拽;命令行的 scp 与 rsync 适合批量和脚本化传输,其中 rsync 还支持增量同步,是大目录反复备份的首选。

FileZilla 是常用的图形界面 sftp 软件,官网 filezilla-project.org 提供各平台安装包。安装后在顶部依次填写主机(sftp://192.168.1.100)、用户名、密码和端口 22,点击“快速连接”。左侧是本地文件树,右侧是服务器文件树,双击进入目录,把文件在两侧之间拖拽即完成上传和下载。它适合传输零散文件和查看目录结构;批量的、要写进脚本的传输,还是命令行更可靠。

scp 的用法和 cp 类似,远处的那一份用“用户名@服务器:路径”表示:

scp reads.fastq.gz meng@192.168.1.100:~/project/data/
scp meng@192.168.1.100:~/project/results/volcano.pdf ./
scp -r result_dir meng@192.168.1.100:~/project/results/

第一行上传,第二行下载,第三行加 -r 递归传输整个目录。rsync 比 scp 更适合大目录和反复同步:它只传输有变化的部分,中断后重跑也不浪费。常用参数组合是 -avP:

rsync -avP reads_dir/ meng@192.168.1.100:~/project/data/reads_dir/

-a 保留权限和时间戳并递归处理目录,-v 显示过程,-P 显示进度并支持断点续传。使用时要留意路径末尾的斜杠:

警告注意|路径末尾的斜杠

rsync 中,reads_dir 表示“这个目录本身”,reads_dir/ 表示“目录里的内容”。源路径多一个斜杠,目标下的层级就会差一层。传完之后最好 ls 检查一下目标目录的结构是否符合预期,再删本地或旧的一份。

基本的linux操作

登录服务器后,所有操作都在 Linux 命令行中完成。本节将围绕文件与文本的查找、查看、筛选和传递,介绍最常用的命令,以及路径、环境变量等基本概念。

先熟悉命令行的样子。一行命令通常由三部分组成:命令名、选项和参数。例如 ls -l ~/data 中,ls 是命令,-l 是选项(列出详细信息),~/data 是参数(要列的目录)。Linux 严格区分大小写,命令一律小写。

三个习惯能显著提高效率:按 Tab 键补全命令和路径,既快又不会拼错;按 ↑ 键翻出执行过的命令;Ctrl+C 中断当前正在运行的命令。用法记不清时,man 命令名 或 命令 --help 随时能查,例如 man ls。

文件与目录

表 2.1: 文件与目录的常用命令
命令 作用 常用形式
pwd 显示当前目录 pwd
cd 切换目录 cd ~/data;cd .. 返回上级
ls 列出目录内容 ls -l 长格式;ls -a 含隐藏文件;ls -lh 大小易读
mkdir 新建目录 mkdir -p a/b/c 连建多级
rmdir 删除空目录 rmdir a
cp 复制 cp file.txt backup/;cp -r dir1 dir2 复制目录
mv 移动或重命名 mv old.txt new.txt
rm 删除 rm temp.txt;rm -r dir 删除目录
chmod 修改权限 chmod 755 run.sh

路径的写法先约定好:/ 开头是绝对路径,从根目录算起;不以 / 开头是相对路径,从当前目录算起。~ 代表家目录,. 是当前目录,.. 是上一级。文件名里的空格和中文在命令行中容易出问题,生信分析的文件名建议只用英文字母、数字、下划线和点。

删除要格外小心:

警告注意|rm 没有回收站

命令行下的删除立即生效,没有回收站可以找回。rm -r 会连目录带内容一起删除,路径写错损失无法挽回。推荐两个习惯:删除前先用 ls 确认路径真实存在、指向预期的对象;拿不准时先用 mv 把待删内容移进一个 trash/ 目录,确认无误后再统一清理。

权限方面,Linux 给每个文件定义三类人(属主、属组、其他人),各有读 r、写 w、执行 x 三种权限。chmod 755 run.sh 用三位数字分别设置三类人的权限:7 = 4+2+1,即读写执行;5 = 4+1,即读和执行。脚本想用 ./run.sh 直接运行,就需要有执行权限;更省事的做法是统一用 bash run.sh 执行,完全不用关心权限位。

查看文件内容

表 2.2: 查看与统计文件的常用命令
命令 作用 常用形式
cat 一次性输出整个文件 cat samples.tsv
less 分页浏览大文件 less run.log
head 看文件开头 head -n 20 counts.txt
tail 看文件末尾 tail -n 20 counts.txt
wc 统计行数、词数、字节数 wc -l counts.txt
diff 比较两个文件的差异 diff old.txt new.txt

生信数据文件常常大到不能直接打开。cat 适合小文件;大文件用 less 分页查看:空格键翻页,b 往回翻,/关键词 搜索,q 退出。head 和 tail 是确认文件内容的捷径——拿到新文件,先 head 看格式对不对;下载完大文件,tail 看结尾是否完整。wc -l 数行数,是检查“文件里到底有多少条记录”的最快方法,后面章节会反复用到。

文本的筛选与处理

下面这组命令把文本当作流来处理,是命令行操作的核心。

表 2.3: 筛选与处理文本的常用命令
命令 作用 常用形式
grep 按模式筛选行 grep SRR1 samples.tsv
cut 按列截取字段 cut -f 1,3 samples.tsv
sort 排序 sort -k2,2n counts.txt
uniq 去除相邻的重复行 sort names.txt | uniq -c
paste 按列拼接 paste names.txt values.txt
sed 流编辑 sed ‘s/,/g’ data.csv

grep 负责找行:grep control samples.tsv 输出所有含 control 的行,-v 反选(排除匹配的行),-i 忽略大小写,-n 显示行号。cut 按列取字段,默认按制表符分隔(-d 可换分隔符),-f 1,3 取第 1、3 列。sort 默认按字典序,-n 按数值排,-r 逆序,-k2,2n 表示按第 2 列的数值排序。uniq 只合并相邻的重复行,所以总是跟在 sort 后面;sort | uniq -c 先排序再计数,是统计“每个值出现了多少次”的标准做法。sed 最常用的是替换:sed 's/旧文本/新文本/g',结尾的 g 表示一行内全部替换。

以样本表 samples.tsv 为例:每行一个样本,三列分别是样本名、分组和测序文件,用制表符分隔。要统计对照组(control)的样本数,或列出所有样本名,分别用下面两条命令链:

grep control samples.tsv | wc -l
cut -f 1 samples.tsv | tail -n +2

第二条里 tail -n +2 表示从第 2 行输出到结尾,正好用来去掉表头。

管道与重定向

注记核心知识|管道:让每个程序只做一件事

上面的例子里,竖线 | 把一个命令的输出直接送给下一个命令当输入,这就是管道(pipe)。Unix 的设计哲学是让每个程序把一件事做好,再用管道把它们串起来,组合出复杂的处理流程。重定向则把输出存进文件:> 覆盖写入,>> 追加写入。

把前面的命令串起来,完成一个小任务——统计样本表里各组的样本数,并保存成文件:

cut -f 2 samples.tsv | tail -n +2 | sort | uniq -c > group_count.txt

我们从左到右读这条命令链:取出第 2 列(分组),去掉表头,排序,计数,最后写入 group_count.txt。后面遇到分析命令,也可以按这个方法一段一段读。

压缩、归档与查找

测序数据动辄几个 GB,传输和保存都离不开压缩。tar 把多个文件打成一个包,gzip 负责压缩,两者结合就是最常见的 .tar.gz:

tar -czvf project.tar.gz project/
tar -xzvf project.tar.gz
gzip reads.fastq
gunzip reads.fastq.gz

-c 创建、-x 解开、-z 走 gzip、-v 显示过程、-f 指定文件名。测序数据更常见的 .fastq.gz 文件通常不必先解压,用 zcat 配合管道就能直接查看或送入下一步处理。

find 按条件递归查找文件:

find . -name "*.fastq.gz" -type f

从当前目录起找出所有 fastq.gz 文件,常与管道配合,把找到的文件交给下一步处理。ln -s 创建软链接(符号链接),给文件或目录起一个稳定的别名:

ln -s /data/project/reads ~/reads

数据换目录时只需要重建链接,脚本里的路径不用改。

进程与会话

跑在服务器上的任务需要看得见、管得住。

表 2.4: 进程与账户相关的常用命令
命令 作用
ps aux 查看所有进程
top 动态查看 CPU、内存占用
w 查看谁在登录、在做什么
kill PID 结束指定进程
passwd 修改自己的密码

ps aux 列出全部进程;top 实时刷新资源占用,按 q 退出。卡住的任务先用这两条找到进程号(PID),再 kill 结束它。w 看当前有哪些人登录,last 看历史登录记录,服务器行为异常时它们是第一手线索。

远程命令行还有个现实问题:本地断网或合上电脑,ssh 一断,正在跑的任务也跟着死掉。tmux 把会话保管在服务器上:

tmux new -s mapping
tmux detach
tmux attach -t mapping

三条命令依次是:新建名为 mapping 的会话(脱离用 Ctrl+B 再按 D)、脱离会话、重新接回。脱离后任务继续在服务器上运行,下次登录 attach 回去就是原来的现场。跑比对、定量这类耗时任务前,先建 tmux 会话再启动,是服务器的标准工作习惯。

环境变量

环境变量是 shell 里带名字的全局值,习惯上全大写。最常用的一个叫 PATH:

echo $PATH

PATH 是一串用冒号隔开的目录。你输入一个命令时,shell 就按顺序在这些目录里找同名程序——这就是为什么装好的软件有时会 command not found:它所在的目录不在 PATH 里。安装 Anaconda 时选择初始化(init),其实就是往 ~/.bashrc 里写了一段把 conda 目录加入 PATH 的配置。

自己也可以设置环境变量:export EDITOR=vim 只在当前会话有效;要长期生效,就把这行写进 ~/.bashrc,再 source ~/.bashrc 重新加载。~/.bashrc 是每次启动 shell 都会执行的配置文件,软件安装器都往里追加内容——环境出问题时先读它,多一分把握。

Shell 脚本与批量处理

将单条命令组织为可检查的批处理。

分析中有大量重复操作,不必每次都逐条手敲。把命令按顺序写进一个文件,交给 bash 执行,就是 Shell 脚本。它能省去重复输入,更重要的是把分析过程保存成文字记录,便于检查、重跑,也便于交给别人复核。

注记核心知识|脚本是分析过程的可核查记录

命令行的历史留在终端里,脚本则把每一步保存在文件中。配合本章最后介绍的版本管理,别人、AI agent,以及几个月后的你,都能逐行检查分析做了什么、为什么这样做。

新建 run_fastqc.sh,写入下面的内容:

#!/bin/bash
set -e
# 为 data 目录下的所有 fastq.gz 文件运行质控
for fq in data/*.fastq.gz; do
    echo "正在处理 $fq"
    fastqc "$fq" --outdir results/fastqc/
done
echo "全部完成"

逐行看:第 1 行 #!/bin/bash 声明用 bash 解释执行;# 开头的是注释,写清楚脚本做什么;set -e 让任何一条命令出错就立即停止,避免错误被后面的步骤掩盖;for 循环把 data/ 下每个 fastq.gz 文件依次赋给变量 fq,$fq 取出变量的值,拼接后缀时推荐写成 ${fq},不会有歧义;echo 输出进度,让你随时知道脚本跑到哪一步。

执行脚本:

bash run_fastqc.sh

也可以先 chmod +x run_fastqc.sh 加执行权限,再 ./run_fastqc.sh 运行,效果相同。入门阶段统一用 bash 运行即可,少关心一件事。

脚本还可以接收参数:$1、$2 依次是执行时跟在脚本名后的第一、第二个参数。例如把单个文件的质控写成 check_one.sh:

fastqc "$1" --outdir results/fastqc/

用 bash check_one.sh data/S1.fastq.gz 就能质控任意指定的文件。同一段处理逻辑需要反复用于不同数据时,用参数传入文件,比复制整个脚本再改名更方便。

两个习惯值得从第一天养成:每个脚本开头写两三行注释,说明用途、输入和输出;先在小数据上跑通,确认无误再放大到全部样本。脚本是给别人看的,也是给几个月后的自己看的——AI agent 读它、改它,同样依赖这些注释和清晰的结构。

使用vscode连接

通过 VS Code 的 Remote-SSH 扩展,你可以在本地编辑器中直接打开服务器上的目录,像使用本地开发环境一样工作。文件树、终端和代码补全都在本地呈现,修改实时同步到服务器。对习惯图形界面的读者,这比纯命令行更容易上手。

安装与连接的完整步骤如下。

  1. 从官网 code.visualstudio.com 下载并安装 VS Code,安装选项保持默认。
  2. 打开 VS Code,进入扩展面板(左侧栏四个方块图标,快捷键 Ctrl+Shift+X),搜索 Remote - SSH,点击 Install 安装。
  3. 按 F1(或 Ctrl+Shift+P)打开命令面板,输入 Remote-SSH,选择 Remote-SSH: Connect to Host → Add New SSH Host,输入例如 meng@192.168.1.100。
  4. 再次执行 Remote-SSH: Connect to Host,选择刚添加的主机,会新开一个窗口,按提示输入密码(配置过密钥登录则直接连上)。
  5. 连接后选择 File → Open Folder,打开服务器上的项目目录(例如 ~/project),左侧文件树显示的就是服务器上的文件。

连接成功后,窗口左下角会显示绿色的 SSH: 主机名。之后新建、编辑、保存文件都直接作用于服务器;按 Ctrl+` 打开的集成终端也是服务器上的 Shell,与 ssh 登录后的环境完全一致。编辑本地脚本再用 scp 传上去的往返流程,从此可以省去。

第 3 步添加的主机实际写入了 ~/.ssh/config 文件。如果 config 里已经有 Host 别名,例如上一节的 lab,它就会直接出现在 Connect to Host 的候选列表里。先配置好密钥登录,再用 Remote-SSH 连接,使用起来最顺手。

2.3 在服务器安装软件

软件安装是配置服务器的主要工作。Linux 各发行版都自带包管理器:Ubuntu、Debian 一系用 apt,Red Hat 一系(Rocky Linux、AlmaLinux 等)用 dnf,命令名不同、用法相近,都是“刷新索引、搜索、安装”三板斧。本书的服务器以 Ubuntu 为例,其他发行版对照使用即可。

用 apt 安装软件

apt(Advanced Packaging Tool)是 Debian 系 Linux 发行版的默认包管理工具,用于管理软件的安装、升级等操作,也包括系统本身的升级。

Ubuntu 的官方源收录了不少常用生信软件,例如 samtools、bwa、bedtools,用一条 apt install 命令就能安装,无需手动编译。不过,官方源中的版本通常偏旧、更新较慢,安装还需要管理员权限。遇到版本太旧或没有收录的软件,可以用下一节介绍的 conda。

提示示例与练习|用 apt 安装 R

以 R 语言为例,两条命令即可完成安装(需要管理员权限,命令前加 sudo):

sudo apt update
sudo apt install r-base

第一条刷新软件源索引——apt 的惯例是安装前先 update,让它知道各软件的最新版本;第二条安装 R 本体。装完确认版本:

R --version

看到版本号输出,安装就完成了。Ubuntu 源里同样收录了 r-bioc-* 系列的 Bioconductor 包,但版本随发行版固定;需要新版 R 或最新的 R 包时,再考虑下一节的 conda。

apt和apt-get命令

apt 命令于 2014 年正式发布,相比 apt-get 系列命令,写法更简洁,也更容易使用。

表 2.5: apt 与 apt-get、apt-cache 命令对照
apt 命令 取代的命令 命令的功能
apt install apt-get install 安装软件包
apt remove apt-get remove 移除软件包
apt purge apt-get purge 移除软件包及配置文件
apt update apt-get update 刷新存储库索引
apt upgrade apt-get upgrade 升级所有可升级的软件包
apt autoremove apt-get autoremove 自动删除不需要的包
apt full-upgrade apt-get dist-upgrade 在升级软件包时自动处理依赖关系
apt search apt-cache search 搜索应用程序
apt show apt-cache show 显示包的详细信息
表 2.6: apt 的软件包查询与软件源编辑命令
新的apt命令 命令的功能
apt list 列出包含条件的包(已安装,可升级等)
apt edit-sources 编辑源列表

apt镜像设置

apt默认的镜像在国内的访问速度是较慢的,所以设置一个国内的镜像是必要的。这里推荐北京外国语大学的开源软件站。其帮助信息完善,例如Ubuntu的镜像设置帮助文档。

在帮助文档中选择你使用的 Ubuntu 版本,获取对应的软件源地址。先备份原配置文件,再按文档修改;完成后执行 sudo apt update 刷新索引,让新配置生效。

图 2.5: 北外镜像站的 Ubuntu 软件源配置页面

2.4 conda 与 Bioconda

系统包管理器之外,生信分析还需要一个能装大量生信软件、能为不同项目隔离环境的工具,这就是 conda。

conda 与 Bioconda

注记核心知识|Anaconda、conda 与 Bioconda

Anaconda 是 Anaconda 公司开发的 Python 发行版,除了 Python 本体,还集成了大量科学计算常用模块,以及该公司开发的 Python 模块和环境管理器 conda。conda 的环境和包管理功能比 Python 本地自带的功能更易用,也能管理非 Python 的模块(Perl、Java、R……)。对生信分析人员来说,Bioconda 这个 conda 源尤其有用:它收录了大量生信分析软件,用一条命令即可安装,不需要手动编译,也不需要 root 权限,安装过程因此简单了很多。

添加相应软件源后,就可以安装其中的包。下面以 IPython 为例:

conda install ipython

conda默认会从Anaconda公司的官方服务器下载模块,而且默认只有官方defaults源一个。其他常用源像conda-forge和Bioconda也需要用户自己添加。另外,官方defaults源对较大规模机构(200人以上)的商业使用有授权限制,社区目前的普遍做法是优先使用完全开放的conda-forge源。这个时候手动添加常用源的国内镜像就十分有必要。

Anaconda的安装

这些镜像网站也提供 Anaconda 安装包,从镜像下载可以避开官网可能出现的卡顿。除了标准版 Anaconda,镜像站还提供体积小得多的 Miniconda:它只包含 Python 和 conda 管理器,其余包需要自己通过 conda 和 pip 安装,适合磁盘空间有限的情况。另一个选择是社区维护的 Miniforge,默认使用 conda-forge 源,安装后即可使用,近年来越来越多人直接以它作为安装入口。

Anaconda 为 Mac 提供 pkg 和 sh 安装包,为 Windows 提供 exe 安装包,为 Linux 提供的则只有 sh 安装包。pkg 和 exe 双击即可安装;sh 需要在命令行中执行,即使从图形界面启动,很多设置仍需在随后打开的终端中完成。

安装 pkg 或 exe 时,会有一步询问是否把 Anaconda 的路径加入环境变量,这里建议勾选。安装器默认不勾选,官方更推荐从开始菜单中的 Anaconda 专用终端启动,两种方式都可用。用 sh 安装时,最后一步会询问是否初始化(init),记得输入 yes。完成这些设置后,重启终端即可使环境变量生效,随后就能正常使用 conda 管理器和相关包。

Anaconda镜像的设置

目前国内最完善的公开Anaconda镜像就是清华大学的TUNA镜像。不过国内部分地区访问清华大学镜像有时候不稳定,可以考虑使用北京外国语大学的镜像,其帮助页面内容由运行维护该站的清华大学TUNA协会同步维护,与清华源基本保持一致,但访问的稳定性很多时候更为优秀。帮助信息提到的存放.condarc配置文件的用户目录,在Linux下使用cd ~命令进入;在Windows下使用cd $env:USERPROFILE命令进入,或者在资源管理器地址栏输入%USERPROFILE%后回车进入。

我们依然推荐你通过上面的链接详细查阅他们的帮助信息,写入在custom_channels范围的镜像地址在使用时只有指定-c参数才会生效。例如如果按帮助页面的信息设置Anaconda配置文件,使用conda install seqkit命令会安装失败,需要使用conda install -c bioconda seqkit命令。

按北外镜像帮助页面的推荐,在家目录下创建或编辑 .condarc 文件,写入下面的内容:

channels:
  - defaults
show_channel_urls: true
default_channels:
  - https://mirrors.bfsu.edu.cn/anaconda/pkgs/main
  - https://mirrors.bfsu.edu.cn/anaconda/pkgs/r
  - https://mirrors.bfsu.edu.cn/anaconda/pkgs/msys2
custom_channels:
  conda-forge: https://mirrors.bfsu.edu.cn/anaconda/cloud
  pytorch: https://mirrors.bfsu.edu.cn/anaconda/cloud

default_channels 把 defaults 源的几个频道指到北外镜像,custom_channels 把 conda-forge 等频道指向镜像站的 cloud 目录。如果你只用 conda-forge,帮助页面还提供一个更精简的版本:channels 只留 conda-forge 并加一行 nodefaults,不再依赖 defaults 源。修改配置后执行一次 conda clean -i 清除缓存的源索引,新镜像即可生效。

Bioconda 频道不在上面这份配置的 channels 列表里——这正是前面 -c bioconda 的由来。想让 bioconda 成为默认频道,可以在 channels 里按 conda-forge、bioconda、defaults 的顺序逐行加入(conda 从上往下按优先级查找),也可以始终用 -c 显式指定,效果相同。

Anaconda环境的管理

注记核心知识|为不同项目隔离环境

不同项目有时需要不同版本的 Python、R 或其他模块。为了避免依赖相互冲突、造成 bug,除了最核心的常用组件,我们通常会为每一类项目单独建立环境。这样,各项目就可以使用自己需要的模块版本。

创建环境

创建环境时,先指定名称,再列出要安装的一个或几个包及其版本。也可以只给名称,不加其他参数,这样建出的环境就不会预装任何包。

conda create -n py3 python=3.12

按名称创建环境时,相关文件会放在 Anaconda 的安装目录下。如果希望放到其他位置,可以用 -p 指定 conda 环境的路径。下面把环境放在 /home/test_conda,并指定 Python 版本为 3.12:

conda create -p /home/test_conda python=3.12

环境建好后用 conda activate py3 进入——装包、跑程序都在这个环境里进行;conda deactivate 退出,conda env list 随时查看已建了哪些环境。进入环境后,提示符前会多出 (py3),看到它就知道自己身在哪个环境。

删除环境

删除环境时,同样可以通过参数指定环境名称或路径。

conda remove -n py3 --all
conda remove -p /home/test_conda --all

Micromamba

早期 conda 最大的痛点是经典求解器计算依赖和扫描各个源的速度都较慢,已安装的包较多时安装过程会明显变慢。Micromamba 用 C++ 重写了这一过程,再加上多线程并行,速度提升了一个数量级;conda 官方从 23.10 版起也把同源的 libmamba 作为默认求解器,所以现在直接使用 conda 通常已经够快。

Micromamba 的独特之处在于它是单个静态可执行文件:不依赖 Python、不依赖 conda,也不需要管理员权限。在服务器上没有装 Anaconda、或者没有 root 权限时,它是搭生信环境最省事的入口;容器和集群环境中也大量使用它。官方安装脚本一条命令即可完成(macOS 也可以 brew install micromamba):

"${SHELL}" <(curl -L micro.mamba.pm)

脚本会把可执行文件安装到 ~/.local/bin(确认它在 PATH 中即可),并自动配置好 shell 集成;重新打开终端就能使用 micromamba 命令,环境默认存放在 ~/micromamba。也可以从项目的 releases 页面直接下载单文件。

它的用法与 conda 几乎一致,把命令名换掉即可;软件源同样读取 ~/.condarc,上一节的镜像配置直接生效。例如创建一个装有 fastqc 和 seqkit 的环境并进入:

micromamba create -n bio -c conda-forge -c bioconda fastqc seqkit
micromamba activate bio

项目开源在 GitHub,完整文档见 mamba.readthedocs.io。

2.5 R 数据处理与绘图基础

具备阅读差异分析代码和处理结果表的能力。

R and Rstudio

R 是生信分析中一种很重要的编程语言。官方软件源 CRAN 收录了大量数据分析和生信相关包,Bioconductor 项目则集中了大多数生信领域的 R 包。

R-base的安装和CRAN镜像设置

R-base 安装包可以从 CRAN 镜像站点获取,这里推荐北外的CRAN镜像。Windows 和 macOS 用户点击各自操作系统的链接,就能进入二进制安装包的下载页面。

图 2.6: CRAN 的 R 安装包下载入口
图 2.7: R for Windows 的基础安装包入口
图 2.8: R for macOS 的安装包下载页面

Linux 用户有管理员权限时,建议用系统包管理器安装;没有管理员权限时,可以用 Anaconda,执行 conda install -c conda-forge r-base 即可安装 R-base。

设置 CRAN 镜像,需要先找到 R 的用户 home 目录。在 R 的交互模式中运行 path.expand("~"),就能查看它的路径。

图 2.9: 在 R 中用 path.expand("~") 获取用户主目录

进入这个目录,检查是否已有 .Rprofile 文件;没有就新建一个空文件。在 .Rprofile 末尾加入 options("repos" = c(CRAN="https://mirrors.bfsu.edu.cn/CRAN/")) 并保存,配置会在新启动的 R 环境中生效。

Rtools

Bioconductor 和 CRAN 上的绝大部分 R 包都提供 Windows 二进制包,安装时无需编译。不过,二进制包的更新一般晚于源码包,也有个别 R 包不提供二进制包。遇到需要从源码编译安装的情况,就要用到 R 官方提供的编译器集合 Rtools。

访问Rtools页面即可获得安装包。Rtools与R的版本配套更新,页面最上方始终提供当前R版本对应的安装包(写作本节时为Rtools45,配套R 4.5及更新版本),且只提供64位版本。如果你使用较老的R版本,可以访问历史版本页面下载对应的Rtools。

图 2.10: Rtools 安装包下载页面

从R 4.2起,Windows上的R会根据安装时写入的注册信息自动发现Rtools,安装后无需配置即可在需要时调用相关编译器。只有使用R 4.1及更早版本搭配Rtools40等旧版Rtools时,才需要按下述旧方法手工配置路径:参照上一节中的path.expand("~")获取R的用户home目录,然后在该目录下编辑.Renviron文件,添加下面的内容。

PATH="D:\Program Files\rtools40\usr\bin;${PATH}"
# 上面分号前的内容是旧版Rtools安装目录下编译器所在路径,
# 应根据实际安装目录进行修改。
# 分号后的内容表示之前已有的PATH环境变量内容,
# 以免覆盖原有环境变量内容。

保存配置文件后,重启 R 的交互环境,运行 Sys.which("make") 检查 Rtools 是否可用。成功时会返回 Rtools 目录下 make.exe 的路径;R 4.2 及更新版本自动发现 Rtools 时,也可以这样检查。之后,遇到源码包版本高于二进制包,或没有二进制包的情况,R 会提示是否编译安装。你可以运行 install.packages("Rcpp", type = "source"),试着从源码编译安装 Rcpp 包。

图 2.11: 在 R 中用 Sys.which("make") 验证 Rtools 已可用

RStudio

R 自带的交互界面只够验证安装,日常写代码推荐使用 RStudio——它是事实上的标准 R 开发环境,免费版对入门完全够用。桌面版从 posit.co 下载安装。它与 R 的关系如同编辑器与解释器:RStudio 只是个外壳,背后调用的还是你装好的 R。

RStudio 界面分四块:左上是脚本编辑器,代码写成 .R 文件保存;左下是 R 控制台,单条命令在这里立即执行;右上显示环境与历史,能看到当前每个变量的值;右下是文件、绘图、帮助面板,画出的图就显示在这里。新手常分不清编辑器和控制台:推荐的工作方式是在编辑器里写代码,按 Ctrl+Enter 把当前行或选中部分送到控制台执行——代码始终留在文件里,而不是散落在会话历史中。

服务器上还有 RStudio Server:R 和 RStudio 都装在服务器上,浏览器打开就能用,本地零安装。数据量大时,它比“下载结果再本地画图”省事得多,不少课题组的服务器预装了它。

建议从一开始就使用 RStudio 的 Project 功能。通过 File → New Project 新建项目后,工作目录固定在项目文件夹,脚本、数据和图形也收在同一处。这与本章最后介绍的项目目录组织是同一个习惯:一个项目用一个目录,可以先从 R 开始练习。

2.6 Python 与结构化配置的最低必要知识

能读懂基础脚本及后续 Snakemake 中的 Python 表达式。

Python 基础速览

下面介绍变量、循环、函数和模块这些必要的 Python 基础。有了这些知识,就足以读懂后续章节的示例代码和 Snakemake 工作流中的 Python 表达式。

不需要专门安装:装好 Anaconda 后,终端输入 python 即进入交互环境,输入 exit() 退出。在交互环境里逐行试代码,是学语言最快的方式,下面所有例子都可以直接照抄运行。

变量与数据类型

Python 里用 = 给变量赋值,常见类型有整数、浮点数、字符串和布尔值:

n_samples = 6                # 整数
depth = 32.5                 # 浮点数
sample_name = "SRR1234567"   # 字符串
is_paired_end = True         # 布尔值

字符串用单引号或双引号都行。拼接字符串最方便的是 f-string:在引号前加 f,变量放进花括号:

report = f"样本 {sample_name} 共 {n_samples} 个,测序深度 {depth}X"
print(report)

处理文件名时常用的字符串方法:sample_name.split("_") 按下划线切成列表,".".join(parts) 用点连回字符串,sample_name.replace("R1", "R2") 替换子串,sample_name.startswith("SRR") 判断前缀。

列表与字典

列表(list)按顺序存一组值,用方括号,元素从 0 开始编号:

samples = ["S1", "S2", "S3"]
samples.append("S4")     # 末尾追加
print(samples[0])        # 第 1 个元素:S1
print(samples[-1])       # 最后 1 个元素:S4
print(len(samples))      # 元素个数:4

字典(dict)存“键→值”的对应关系,用花括号,生信配置里到处都是它:

groups = {"S1": "control", "S2": "treatment", "S3": "control"}
print(groups["S2"])          # treatment
groups["S4"] = "treatment"   # 新增一项

循环与分支

for 遍历列表或字典,if 按条件分支。注意 Python 靠缩进表示代码块,冒号后换行缩进四个空格:

for sample in samples:
    if groups[sample] == "treatment":
        print(f"{sample} 是处理组")
    else:
        print(f"{sample} 是对照组")

配合 range 可以批量生成数字:for i in range(1, 9) 会依次取 1 到 8。

函数

函数把一段逻辑打包复用,def 定义,return 返回结果:

def get_sample_id(filename):
    """从文件名提取样本 ID,如 S1_L001_R1_001.fastq.gz → S1"""
    sample_id = filename.split("_")[0]
    return sample_id

print(get_sample_id("S1_L001_R1_001.fastq.gz"))

函数名后的三引号字符串是文档说明,写清输入和输出,别人和 AI agent 都能读懂。这与前面 Shell 脚本一节的思路一致:虽然语言不同,我们都要把处理过程写下来,让它可以复用,也可以检查。

文件读写与模块

读文件用 with open,它保证文件用完自动关闭:

with open("samples.tsv") as f:
    header = f.readline().strip()
    for line in f:
        fields = line.strip().split("\t")
        print(fields[0], fields[1])

这段代码逐行读取文件,用 strip() 去掉行尾换行符,再用 split("\t") 按制表符切列。这是处理表格文件时常用的基本步骤。写入文件时,需要加上模式参数:with open("out.txt", "w") as f: f.write("...")。

Python 的许多功能由模块提供,用 import 导入后即可使用。例如,os.path 处理路径,csv 读写表格,subprocess 在脚本里调用外部命令,后续章节会陆续用到它们。

这一节不要求学完 Python 的全部内容,先练习读懂脚本:看到一段代码,能说出每个变量是什么、循环在遍历什么、结果写到哪里。暂时写不出来的部分,可以先照着例子运行,也可以请 AI agent 逐行解释,但每一行的含义仍要自己弄明白。

Jupyter

Jupyter 是一个非营利开源项目,2014 年从 IPython 项目中诞生,此后不断发展,通过网页支持几乎所有编程语言的交互式数据分析与科学计算。最早的项目是 IPython Notebook,后来改名为 Jupyter Notebook;如今,项目的核心是 JupyterLab。如果你用过 Jupyter Notebook,迁移到 JupyterLab 的学习成本很低,第一眼最明显的变化可能就是多标签和侧边栏。JupyterLab 现已发展到 4.X 版本,经典的 Jupyter Notebook 仍在并行维护,扩展生态也相当成熟。

安装JupyterLab

PyPI 和 Anaconda 都收录了 JupyterLab,安装很方便。这里仍建议使用前面介绍的独立包管理器 micromamba:

pip install jupyterlab # pypi安装
conda install jupyterlab # anaconda安装
micromamba install jupyterlab # micromamba安装

内核安装

JupyterLab安装时只支持Python,如果需要支持其他语言,需要自己安装相应的内核。例如R语言需要安装R包IRkernel,然后在R交互模式中使用IRkernel::installspec()命令注册内核到JupyterLab。而Julia语言则需要安装Julia包IJulia,然后通过build IJulia命令来注册内核。

本地和远程使用

在本地启动 JupyterLab,先打开终端,切换到准备进行分析的目录。Windows 用户可以选择 PowerShell,或通过 Windows Terminal 打开其他终端。Jupyter 只能读取启动目录及其子目录下的文件,因此要先选好目录,再运行 jupyter lab。默认浏览器会自动启动,打开 JupyterLab 页面。

远程使用服务器上的 JupyterLab,需要多做一步端口映射。在本地终端用 ssh 把服务器上 JupyterLab 监听的端口映射到本地计算机。执行下面的命令会登录远程服务器,再运行 jupyter lab 启动服务器上的 JupyterLab。随后在本地浏览器访问 127.0.0.1:1234,就能连接服务器的 8888 端口。命令中的 username 是服务器用户名,serverip 是服务器 IP 地址;1234 是希望使用的本地端口,8888 是远程服务器的端口。

ssh username@serverip -L 127.0.0.1:1234:127.0.0.1:8888
警告注意|以实际启动端口为准

如果服务器上已有其他用户,或你上次启动的 JupyterLab 尚未关闭,远程端口可能不是 8888。因此,更推荐先用 ssh 登录服务器(可以用 MobaXterm 等 ssh 软件,也可以用 ssh 命令),启动 JupyterLab,查看启动信息中的实际端口号,再据此修改上面映射命令里的远程端口。

结构化配置:YAML 与 JSON

配置文件是分析流程的常见输入:样本表、软件参数、工作流规则经常以 YAML 或 JSON 等结构化格式描述。读懂它们,是修改他人流程、编写 Snakemake 规则的基础。

YAML 用“缩进 + 冒号”表达结构,可读性最好,是 Snakemake 等各类流程配置文件的主流格式。一个生信项目常见的 samples.yaml 长这样:

project: rnaseq_demo
genome: hg38
threads: 8
samples:
  S1:
    condition: control
    fastq: data/S1.fastq.gz
  S2:
    condition: treatment
    fastq: data/S2.fastq.gz

顶层的 project、genome、threads 是键值对;samples 下面缩进一层,是嵌套的字典,每个样本又是一层。列表用短横线表示:

comparisons:
  - treatment_vs_control
  - knockout_vs_wt

YAML 的规则极少:冒号后要有一个空格;层级关系完全靠缩进表达,同层元素必须对齐;字符串一般不需要引号。

警告注意|缩进用空格,不要用 Tab

YAML 只认空格缩进,编辑器插入 Tab 是配置报错的第一原因,报错信息里的 found character that cannot start any token 多半指它。让编辑器把 Tab 转为空格(VS Code 默认如此),这个坑就绕开了。

JSON 可以表达同样的结构:花括号表示对象,方括号表示数组,键要加双引号,元素之间用逗号分隔。把上面两份 YAML 合成一份 JSON,写法如下:

{
  "project": "rnaseq_demo",
  "genome": "hg38",
  "threads": 8,
  "samples": {
    "S1": {"condition": "control", "fastq": "data/S1.fastq.gz"},
    "S2": {"condition": "treatment", "fastq": "data/S2.fastq.gz"}
  },
  "comparisons": ["treatment_vs_control", "knockout_vs_wt"]
}

JSON 没有 YAML 好读,但它是程序间交换数据的标准格式,网页、API 和各类软件的结果文件大量使用。生信实践中两者各就其位:人手写、人手改的配置用 YAML,程序输出和互相传递用 JSON。

读取这些文件也有现成工具。在 Python 中用 import json 与 import yaml 导入相应模块(后者随 Anaconda 提供),再用 json.load(open("config.json")) 就能把文件读成字典,随后按上一节介绍的方法取值。配置文件把参数值单独放出来,修改这些值时就不必改代码。

2.7 本地AI agent的配置与安装

在本地装好 AI agent,让它们参与代码编写与排错。

Claude Code、Codex、ZCode 等命令行 AI agent 可以在终端里读写代码、执行命令、完成多步骤任务,是 AI 时代生信分析的重要本地工具。使用它们的前提是完成订阅(coding plan)与 API 设置,并清楚它们擅长什么、可能在什么地方出错。

coding plan 和 API 设置

AI coding agent 的使用方式有两类,先分清楚:

  • coding plan(订阅计划):按月或按年订阅,如 Anthropic 的 Claude Pro/Max、OpenAI 的 ChatGPT Plus/Pro、智谱的 GLM Coding Plan。订阅后客户端内直接使用,按对话量计限额,成本可控,适合日常高频使用。
  • API key(按量付费):在平台申请一串密钥,程序调用时验证身份,按实际用量计费。偶尔调用很便宜,跑大批量任务时要留心费用。

本书推荐入门读者从 coding plan 开始:费用固定,配置也最简单。各家 plan 支持的客户端不同——Claude Pro/Max 用于 Claude Code,ChatGPT Plus/Pro 用于 Codex,GLM Coding Plan 则可以同时驱动 Claude Code 和 ZCode(配置方法见下面两节)。

API key 本质是账户的钥匙,保管规则只有一条:绝不泄露。不要把 key 写进脚本或配置文件再提交到 Git,不要贴进聊天群或论坛。正规服务不会向你索取 key,凡是索要的,一律当作骗局。

警告注意|环境变量是存放密钥的正确位置

程序从环境变量读取密钥(如 ANTHROPIC_API_KEY)是通行做法:key 不出现在代码里,也就不会被提交进仓库。上一节环境变量的知识在这里直接用上。本地机器自用时,把 export 语句写进 ~/.bashrc(或各家客户端自己的配置文件)即可。

Claude Code

Claude Code 是 Anthropic 推出的命令行 AI agent,能在终端里读写代码、执行命令、跨文件完成多步修改,是生信分析中最常被提到的 coding agent 之一。

安装需要 Node.js 18 及以上版本(可用 conda install -c conda-forge nodejs 安装,或从官网下载),然后一条命令完成安装:

npm install -g @anthropic-ai/claude-code

进入项目目录,输入 claude 即启动,首次按提示登录 Anthropic 账号(Claude Pro/Max 订阅即可使用)。

国内读者也可以用 GLM Coding Plan 驱动 Claude Code:订阅后在智谱开放平台获取 API key,编辑(没有则新建)~/.claude/settings.json,写入:

{
  "env": {
    "ANTHROPIC_AUTH_TOKEN": "你的智谱 API Key",
    "ANTHROPIC_BASE_URL": "https://open.bigmodel.cn/api/anthropic"
  }
}

保存后重新启动 claude,请求即走 GLM 通道。具体步骤以智谱官方文档为准:在 Claude Code 中使用 GLM Coding Plan。

Codex

Codex CLI 是 OpenAI 的开源命令行 AI agent,定位与 Claude Code 相同。安装方式二选一:

npm install -g @openai/codex
brew install codex

Codex 在 Git 仓库内工作效果最好:它能读提交历史、理解项目结构,修改前后还可以用 git diff 对照。因此,建议在项目目录里先执行 git init,再启动 codex。首次启动时,按提示登录 ChatGPT 账号(Plus/Pro 订阅),或配置 OpenAI API key。

ZCode

ZCode 是智谱推出的桌面版 AI coding 客户端,把 agent 对话、文件编辑和终端集成进图形界面,不习惯命令行的读者上手最容易。到官网 zcode.z.ai 下载 macOS 或 Windows 客户端安装,启动后用 GLM Coding Plan 或 API key 登录即可使用。安装说明见官方文档,项目本身开源在 GitHub。

三款工具功能定位相近,选一到两款深入使用即可。后面各章会反复用到同一个习惯:让 agent 做事,同时检查它的每一步,读它改的代码、看它跑的命令、验证它给的结果。

2.8 AI时代的版本管理

形成可维护的工作习惯,遇到错误能够定位原因。

项目目录的组织

生信项目最忌讳“文件摊一桌”。推荐从第一个项目起就固定目录骨架:

rnaseq_project/
├── data/
│   ├── raw/          # 原始测序数据,只读不动
│   └── clean/        # 过滤清洗后的数据
├── scripts/          # 分析脚本
├── results/          # 分析结果
│   ├── tables/
│   └── figures/
├── samples.tsv       # 样本表:项目的事实清单
└── README.md         # 项目说明

一条命令建好骨架:

mkdir -p rnaseq_project/{data/{raw,clean},scripts,results/{tables,figures}}

目录建好后,原始数据放进 raw/ 就不再修改,后续处理都生成新文件,写入下游目录,出错时才能回到起点。样本表 samples.tsv 一行一个样本,记录样本名、分组和文件路径;脚本从表中读取信息,不把样本名写死在代码里,这样增加样本时只需改表。README.md 哪怕只写三行,也要交代项目做什么、数据从哪来、按什么顺序运行。数据、脚本、结果分开存放,就容易看清哪些文件可以重新生成:results 中的结果都能由 scripts 和 data 再生,丢失后也可以重新得到。

版本管理与 Git

AI agent 会大量修改你的代码,改坏了怎么办?这就需要版本管理。Git 记录每次提交的完整快照,随时可以对照、回退,配合远程仓库还能异地备份。用 AI 修改代码时,git diff 能把每次改动展示出来,供你审查。因此,学会使用 AI agent 之后,还要学会用版本管理检查它的工作。

最小工作流只需四条命令:

git init
git add scripts/ samples.tsv
git commit -m "添加样本表与质控脚本"
git log --oneline

这四条命令依次完成:在项目目录初始化仓库,把文件纳入跟踪,提交一版快照并附说明,再查看提交历史。日常使用时,围绕 add、commit、diff 操作,改一批就提交一次。commit message 要写给未来的自己、协作者和 AI 看;只写“update”“fix”,并不能交代这次具体改了什么。

生信仓库必须配一个 .gitignore,把大文件和生成物挡在仓库外:

data/
results/
*.fastq.gz
*.bam

测序数据动辄数 GB,放进 Git 仓库会让它膨胀到无法使用;results 能由脚本再生,也不必跟踪。Git 管代码、脚本和配置,数据另用 rsync 或网盘备份,两者不要混。

远程备份:在 GitHub(或单位 Git 服务)建一个私有仓库,按页面提示 git remote add origin ... 之后 git push -u origin main,以后每次提交随手 push。换了电脑或仓库丢失,整份 clone 回来——“代码永远有多份”是研究数据安全里成本最低的一条。

排错的基本思路

分析出错是常态,排错能力比不出错更值得练。一套固定的动作能解决大部分问题。

下图给出四步排查的顺序。每一步都可能解决问题:解决了,就从右侧出口转到记录收尾;没有解决,再进入下一步。

图 2.12: 排错的基本流程

第一,读报错。从输出里找 error 而不是 warning——warning 是提醒,error 才是失败原因。程序崩掉时,最后几行通常就是关键信息;找不到就把整段输出从头读,第一条 error 之后的内容往往是连锁反应,修好它,后面自然消失。把报错原文复制下来,不要凭印象转述。

第二,最小复现。整个流程报错,就把出错那一步单独拿出来,用最小的输入跑一遍:全部样本失败,先拿一个样本试;脚本失败,先把循环里那一条命令手动敲一遍。问题缩到最小,原因往往自己浮出来。

第三,查输入。很多“程序坏了”其实是数据不对:用 head 看文件开头的格式,用 wc -l 数行数,再和上一步的输出核对。先检查传输是否出错、表头是否变化、路径是否少了一层,再考虑软件本身是否有 bug。

第四,问对问题。向同事或 AI agent 求助时带上三样东西:完整报错原文、你执行的命令、期望结果与实际结果。AI agent 很擅长解释报错、给出排查步骤,但它也会自信地猜——每一条建议都要自己验证过再往前走。

最后,把解决过程记下来,一行就够:“某报错,原因是 X,改法 Y”。同样的错第二次遇到时,你会感谢第一次的记录。