简介:面向生物计算与药物设计初学者,以及需要把分子对接任务迁移到集群的研究人员,这份PDF文档围绕Autodock Vina批量分子对接展开,兼顾Ubuntu 18.04环境搭建与Slurm作业调度两条主线。内容涉及Open Babel、Autodock Vina、MGLTools的安装与依赖处理,受体和配体预处理、conf.txt参数设置、pdbqt结果转sdf等关键环节,并呈现vina.sh批处理脚本的组织思路;后半部分讲解munge、slurm-wlm、slurmd与slurmctld的配置及slurm.conf编写,帮助读者理解如何将对接任务提交到集群批量运行。资源包仅含1个PDF文件,大小约1013KB,篇幅紧凑、便于随查随用。目前已有5264人学习,适合希望打通“单机对接—脚本批处理—集群调度”流程、积累可复现实验经验的读者参考。
1. 装之前先认清这套组合:Ubuntu 18.04 加 Python 2.7 是绕不开的前提
Autodock Vina 批量分子对接表面上只是「准备受体、准备配体、循环调用 vina」三步,真正让人装到半夜的,全是版本和路径。我印象最深的一次翻车,是在一台默认 Python 3 的机器上照老步骤装 MGLTools 1.5.6,install.py 刚跑就抛语法错误——整套 MGLTools 是 Python 2 时代的东西;换回 Ubuntu 18.04 之后才一路顺到 vina 出结果。Ubuntu 18.04、Open Babel、Vina 1.1.2、MGLTools 1.5.6 再加 Slurm 排队,是批量对接里最常见的一套组合:十几个配体单机还能扛,上百个就必须上调度。下面按实际安装顺序来,先把依赖和版本钉死,再装三件套、跑通批量脚本,最后动 Slurm 和三节点。
2. 依赖和版本先钉死:apt 清单、三个安装包与解压路径
这一步最容易被跳过,也最容易在后面以「找不到命令」「ImportError」的形式反咬你。Ubuntu 18.04 自带 python 命令指向 Python 2.7,正好是 MGLTools 1.5.6 需要的解释器版本;如果换成 20.04 之后的系统,python 已经指向 3.x,install.py 会在第一轮语法解析就挂掉。所以系统版本不是随便挑的,是这套工具链倒推出来的。
2.1 一条 apt 命令装齐 X11 与 Python 2 依赖
我一般不在装到一半时零散补包,而是一次把编译头文件、图形库、Python 2 扩展全部装上,避免中途发现缺依赖再回头。命令长,但每条都有用:
sudo apt-get update sudo apt-get install -y build-essential libxt-dev libglu1-mesa-dev \ libxmu-dev libxi-dev libpng-dev libjpeg-dev libtiff-dev \ csh python-tk python-numpy python-dev python-pmw逐项说清楚它们为什么必须存在:build-essential提供 gcc 和 make,MGLTools 安装时有一部分 C 扩展要现场编译,缺了会在 install.py 中途报command 'gcc' failed;libxt-dev、libxmu-dev、libxi-dev是 X11 的开发头,MGLTools 里的 AutoDockTools 和 PMV 都链接这些库,哪怕你只跑命令行脚本、不打开图形界面,Python 模块导入时也会去找它们;libglu1-mesa-dev提供 OpenGL 的 GLU,PMV 渲染分子结构要用;libpng-dev、libjpeg-dev、libtiff-dev对应图像读写;csh是因为 MGLTools 里残留了一些 csh 写的辅助脚本;python-tk和python-pmw是 ADT 图形界面的 Tk 组件,python-numpy与python-dev供数值计算和扩展编译使用。
提示:
apt-get update之后如果卡在Waiting for headers或者提示 dpkg 被锁,先用sudo lsof /var/lib/dpkg/lock看是谁占着,别再开第二个 apt 会话,锁冲突会把包管理器状态搞乱。
2.2 三个安装包的版本选择与解压
组件版本不是越新越好,这套链条里每一个都跟脚本写法绑定:
| 组件 | 版本 | 包形态 | 装法 | 备注 |
|---|---|---|---|---|
| Open Babel | apt 源内版本 | deb 包 | apt install | 只用来做 sdf/mol2/pdbqt 格式转换 |
| AutoDock Vina | 1.1.2 | 预编译二进制 tgz | 解压即用 | 命令行参数与老脚本完全对得上 |
| MGLTools | 1.5.6 | tar.gz 源码目录 | 解压后python install.py | 依赖 Python 2.7 |
Vina 选 1.1.2 的理由很实际:它是预编译二进制包,不用自己处理 Boost 依赖,解压后bin/vina直接能跑,参数和大量现成脚本一致。这个包名里带x86,在 64 位系统上一般也能正常执行,真跑不起来再用file看一眼二进制架构,别急着怀疑程序本身。
mkdir -p /home/autodock cd /home/autodock # Vina 预编译包,解压出 autodock_vina_1_1_2_linux_x86/ tar -zxvf autodock_vina_1_1_2_linux_x86.tgz # MGLTools 1.5.6,解压目录名是 mgltools_x86_64Linux2_1.5.6 tar -zxvf mgltools_x86_64Linux2_1.5.6.tar_.gz # 确认真实解压出来的目录名,后面三条 PATH 全靠它 ls -d /home/autodock/*1.5.6* /home/autodock/*vina*tar的四个参数分工:-z处理 gzip 压缩,-x解包,-v打印解出的文件,-f指定归档文件。最后那条ls不是多余的,MGLTools 的目录名在文档里常被写成MGLTools-1.5.6,而包实际解出来是mgltools_x86_64Linux2_1.5.6,名字差一个字符,PATH 就全指空,这是后面最常见的连锁故障源头。
2.3 MGLTools 1.5.6 的 install.py 必须用 Python 2 跑
装 MGLTools 不是编译,它本质上是把 MGLToolsPckgs 下的模块摊开、生成路径配置,所以 install.py 必须由 Python 2.7 解释。Ubuntu 18.04 上python就是 2.7,直接跑即可;如果系统里已经改过默认解释器,显式写python2更保险。
cd /home/autodock/mgltools_x86_64Linux2_1.5.6 python -V # 必须是 Python 2.7.x,不是就别往下走 python install.py # 安装目录交互提示直接回车,用当前目录install.py 会依次检查依赖、复制脚本、写入~/.mgltools_1.5.6的路径配置,最后提示安装完成。中途如果抛SyntaxError,八成是解释器版本不对;如果抛ImportError: No module named Tkinter,回去补python-tk。装完立刻验证脚本是否在:
ls MGLToolsPckgs/AutoDockTools/Utilities24/ | grep prepare_正常应看到prepare_receptor4.py、prepare_ligand4.py、prepare_gpf4.py等一批以prepare_开头的脚本,它们就是批量对接的主力。
2.4 三条 PATH:少一条,脚本就会在中间断掉
这套工具的可执行文件分散在三个目录里,vina.sh顶部的三条 export 不是仪式,是硬要求:
export PATH=/home/autodock/autodock_vina_1_1_2_linux_x86/bin/:$PATH export PATH=/home/autodock/mgltools_x86_64Linux2_1.5.6/bin/:$PATH export PATH=/home/autodock/mgltools_x86_64Linux2_1.5.6/MGLToolsPckgs/AutoDockTools/Utilities24/:$PATH第一条给的是vina可执行文件;第二条bin/下是pmv、adt等启动脚本;第三条Utilities24/下才是prepare_receptor4.py、prepare_ligand4.py这些 Python 脚本。第三条最容易被漏,漏了的表现是prepare_ligand4.py: command not found,而很多人会误以为是 MGLTools 没装好,回去重装一遍,白折腾一小时。
注意:这三条一定要写在
vina.sh和后面的 sbatch 作业脚本里,不要只写进~/.bashrc。批处理作业由 slurm 起的是非登录 shell,.bashrc里的 env 不一定被加载;靠.bashrc的环境变量有时能跑通,有时报找不到命令,属于典型的玄学故障。
3. 批量对接脚本落地:受体准备一次,配体循环到底
单机脚本写对了,后面搬到 Slurm 上就是把最外层套一个 sbatch 外壳的事。所以这一章先在单机上把整条链路走到output.sdf,再谈集群。整条链路是:受体 pdb 转 pdbqt、配体 sdf 转 mol2 并按分子拆分、逐个准备成 pdbqt、调 vina 对接、把结果转回 sdf 汇总。
3.1 受体预处理:先把水和原配体摘掉
prepare_receptor4.py把 PDB 转成 Vina 能读的 pdbqt,会自动加极性氢、合并非极性氢、分配 Gasteiger 电荷。但输入 PDB 里往往带结晶水和原配体,这些东西留在受体里会让对接盒子被干扰,甚至把结果位点带偏。
cd /home/autodock # 去掉结晶水,保留蛋白主体 grep -v -E '^(HOH|WAT)' pro.pdb > receptor_clean.pdb # 转 pdbqt:-r 输入受体,-o 输出文件 prepare_receptor4.py -r receptor_clean.pdb -o receptor.pdbqt # 检查输出里原子数,太小的输出说明转换失败 grep -c '^ATOM' receptor.pdbqt-e这个参数在老脚本里也常出现,作用是遇到非法残基或坏原子时直接报错退出,而不是静默产出一个残缺的 pdbqt。批量场景我倾向加上它:批量跑最怕的就是「以为跑完了,其实全是空文件」。至于原配体,不要一刀切删掉 HETATM——金属离子、辅因子往往是活性位点的一部分,删之前看一眼它是不是你要对的那个口袋。我一般的做法是把原配体坐标单独存一份,既用来定盒子中心,又作为后续构象对比的参考。
3.2 配体拆分:obabel -m 的命名规则要心里有数
配体来源通常是 SDF 格式的多分子文件,先整体转 mol2,再按分子拆成单文件,一个分子一次对接:
# sdf 转 mol2,-i/-o 指定输入输出格式,-O 指定输出文件名(大写 O) obabel -isd testset.sdf -omol2 -O testset.mol2 # 按分子拆分,-m 会输出 vs1.mol2、vs2.mol2、vs3.mol2…… obabel testset.mol2 -O vs.mol2 -m-m的命名规则是「原文件名 + 序号」,vs.mol2会变成vs1.mol2、vs2.mol2。这个规则本身没问题,坑在于拆分目录的清理:如果上一次跑剩下的vs7.mol2还在,这一次只拆出 6 个分子,循环里就会把旧的第七个也跑一遍,汇总结果里凭空多出一条。所以脚本里rm -rf mols && mkdir mols不是洁癖,是必须的清理动作。另外,拆分出来的文件数和源 SDF 里的分子数要对得上,对不上说明源文件里有解析失败的分子,先修源文件再跑对接。
3.3 conf.txt:盒子中心和尺寸是最容易拍脑袋的部分
Vina 的所有对接参数都在这一个文件里,脚本里用--config指过去:
receptor = /home/autodock/receptor.pdbqt ligand = ligand.pdbqt center_x = 12.31 center_y = -4.87 center_z = 28.06 size_x = 22 size_y = 22 size_z = 22 exhaustiveness = 8 num_modes = 9 energy_range = 3 cpu = 1 seed = 42| 参数 | 作用 | 取值建议 |
|---|---|---|
receptor | 受体 pdbqt 路径 | 建议写绝对路径,避免工作目录切换后失效 |
ligand | 配体 pdbqt 路径 | 循环里每个分子同名生成,写相对名即可 |
center_x/y/z | 搜索盒中心坐标 | 用原配体质心或活性位点残基坐标,别手估 |
size_x/y/z | 盒子三边长度(Å) | 常规 20~25;配体大就放大到 25~30 |
exhaustiveness | 搜索彻底程度 | 批量筛选 8 够用,精修可到 16~32 |
num_modes | 最多输出构象数 | 默认 9,够后续排序 |
energy_range | 输出构象的能量窗口 | 3 kcal/mol,太大等于没筛 |
cpu | 单任务核数 | 必须与 Slurm 分配的核数一致 |
盒子中心是整份文件里最不该拍脑袋填的。如果晶体结构里带原配体,用它算质心是最省事的办法:
# 从带原配体的 pdb 里算 HETATM 质心,作为盒子中心初值 import sys xs = ys = zs = 0.0 n = 0 for line in open(sys.argv[1]): if line.startswith("HETATM"): # PDB 固定列:x=31-38,y=39-46,z=47-54(Python 切片从 0 计) xs += float(line[30:38]) ys += float(line[38:46]) zs += float(line[46:54]) n += 1 print(f"center_x = {xs / n:.2f}") print(f"center_y = {ys / n:.2f}") print(f"center_z = {zs / n:.2f}")用法是python3 center.py lig_and_protein.pdb,输出三行直接粘进 conf.txt。参数说明:脚本只统计HETATM行,所以输入必须是同时含蛋白和原配体的完整结构文件;如果原配体是多个片段,质心会被拉到中间,这时改用活性位点关键残基的 CA 原子坐标均值更稳。盒子尺寸跟着配体走:可旋转键多的大配体,20 Å 的盒子装不下,出来的构象是被盒子边界截断的。
3.4 循环体怎么写才不互相覆盖
循环里最容易出的问题是文件互相覆盖和结果重复追加。下面这个版本是我实际在用的骨架:
#!/bin/bash # vina.sh:单机串行版,后面改成 sbatch 作业脚本 set -e export PATH=/home/autodock/autodock_vina_1_1_2_linux_x86/bin/:$PATH export PATH=/home/autodock/mgltools_x86_64Linux2_1.5.6/bin/:$PATH export PATH=/home/autodock/mgltools_x86_64Linux2_1.5.6/MGLToolsPckgs/AutoDockTools/Utilities24/:$PATH WORKDIR=/home/autodock cd $WORKDIR rm -rf mols output.sdf failed.txt mkdir mols cd $WORKDIR/mols for mol2 in *.mol2; do base="${mol2%.mol2}" # 配体转 pdbqt,每个分子独立命名,避免互相覆盖 prepare_ligand4.py -l "$mol2" -o "${base}.pdbqt" || { echo "PREP_FAILED $mol2" >> ../failed.txt continue } if vina --config ../conf.txt --ligand "${base}.pdbqt" \ --cpu 1 --out "${base}_out.pdbqt" --log "${base}.log"; then obabel -ipdbqt "${base}_out.pdbqt" -osd -O "${base}.sdf" cat "${base}.sdf" >> ../output.sdf else echo "VINA_FAILED $mol2" >> ../failed.txt fi # 只删中间产物,保留 log 便于回溯 rm -f "${base}_out.pdbqt" "${base}.sdf" done逻辑说明:base="${mol2%.mol2}"去掉后缀做前缀,保证每个分子的 pdbqt、log、sdf 都是独立文件名,不共用ligand.pdbqt这种通用名——通用名在单进程里没事,一旦并发就会互相踩。|| { ... continue; }让单个配体准备失败时跳过而不是整批中断,失败清单落到failed.txt里,跑完一眼能看到哪些分子没成。set -e保留着,是为了让环境类错误(比如 PATH 没设好导致第一条命令就找不到)立刻失败,别在错误的环境里跑完整批。
原脚本里vina --config ../conf.txt而不指定--ligand,靠的是 conf.txt 里写ligand = ligand.pdbqt,配合循环里每次都生成同名文件。这种写法能跑,但一旦并发或中途中断,残留的ligand.pdbqt会被下一个分子误用。显式传--ligand是更安全的做法,命令行参数优先级高于 conf.txt 里的同名项。
3.5 单机先跑通一个分子,再谈批量
批量脚本第一次执行不要直接上全量。先把mols目录里只留一个 mol2,跑一遍,确认三件事:vina那一步在 log 里有正常的打分输出;output.sdf里至少有一条完整记录;failed.txt不存在或为空。一个分子从准备到出结果通常几十秒到几分钟,exhaustiveness 8时更接近前者。
跑通之后再放全量,用time ./vina.sh记一下总耗时。这个数字决定了你要不要上 Slurm:单机跑 100 个分子要十几个小时,而且中途断了没法续跑,那就该进下一章了。
4. Slurm 从单机到三节点:munge 先通,slurm.conf 后改
Slurm 的安装顺序有讲究:认证层没通,后面的slurmd起不来,你会误以为是 slurm.conf 写错了,然后在一个本来没错的配置上反复改。所以第一步永远是 munge,验证通过再碰 Slurm 本体。
4.1 munge 单独验证:不通过就别往下走
munge 负责节点之间的身份认证,Slurm 的AuthType=auth/munge和CryptoType=crypto/munge都依赖它:
sudo apt-get install -y munge libmunge-dev libmunge2 sudo systemctl enable munge sudo systemctl start munge sudo systemctl status munge # 本机自测:能编码再解码,说明 key 和 socket 都正常 munge -n | unmungemunge -n生成一个凭证,unmunge把它解开。如果这一步报Failed to connect to socket,看systemctl status munge的日志;如果是Invalid credential,大概率是/etc/munge/munge.key的权限不对——必须是munge:munge且0400,任何人可读都会让 munged 拒绝启动:
sudo chown munge:munge /etc/munge/munge.key sudo chmod 400 /etc/munge/munge.key sudo systemctl restart munge多节点时这份 key 必须三台完全一致,做法是从控制节点scp到另外两台,再各自重启 munge。不同 key 的集群,sinfo会显示节点状态异常,报错信息往往只写Unable to establish connection,不会告诉你 key 不一致——这是血泪经验里最贵的一条。
4.2 slurm-wlm、slurmd、slurmctld 的安装与目录准备
sudo apt-get install -y make hwloc libhwloc-dev \ mariadb-server libmysqlclient-dev sudo apt-get install -y slurm-wlm slurmd slurmctld硬件拓扑库hwloc是 Slurm 识别 CPU 和 NUMA 结构用的;mariadb-server和libmysqlclient-dev只有在你打算接slurmdbd做作业记账时才必须,三节点小集群不接数据库也能正常排队,少一个故障点。
Ubuntu 打包的 Slurm 有个路径差异必须提前确认:配置常常在 `/etc/slurm-llnl/slurm
本文还有配套的精品资源,点击获取