资讯详情

Ubuntu下Autodock Vina+Slurm批量分子对接实践

📅 2026/10/29 6:43:25 | 华诺云谱 👁 阅读
Ubuntu下Autodock Vina+Slurm批量分子对接实践
简介围绕 Autodock Vina 批量分子对接与 Slurm 集群调度整理的实战型 PDF 文档面向生物信息学、计算生物学及药物设计方向的学习者与科研人员可用于在 Ubuntu 18.04 上搭建对接环境并把单次对接扩展为集群批量任务。文档以 1 个 PDF 文件交付压缩包约 1013KB篇幅紧凑便于随查随用。内容覆盖 Open Babel、MGLTools 与 Vina 的安装配置受体和配体预处理、conf.txt 参数设置及 pdbqt 结果转换并延伸至 Slurm 的 munge 认证、slurm.conf 编写与服务启动形成从软件部署到作业调度的完整链路。已有 5257 人学习适合需要理解批量对接流程、集群资源分配与常见配置思路的读者参考。1. 从一台机器上的 500 个配体说起这套 Autodock Vina Slurm 组合解决什么问题一个中等规模的虚拟筛选500 个配体Autodock Vina 单次对接十几秒到两分钟串行跑完是四到八个小时。这期间终端不能断、机器不能重启而最可能的结果是跑到第 400 多个时某个 mol2 里混进一个 Vina 不认识的原子类型脚本当场退出前面几百个中间结果因为用了rm清理全白跑。分子对接的计算形态极其规整——任务之间完全独立、单个任务耗时不长、总量却很大这种形态天生该并行硬扛在单机上纯属浪费。这份材料做的事情就是把链路跑通Ubuntu 18.04 上装 Open Babel、Autodock Vina、MGLTools 三件套用一段vina.sh把 sdf 拆成一个个配体批量对接、结果合并再装 Slurm把串行脚本改成 sbatch 作业扩到三个节点用 NFS 共享同一份工作目录并行跑。适合刚接触分子对接、手里攥着一批分子要筛、又被串行脚本卡住的人也适合已经会跑单机 Vina、想把它搬上调度器但不知道 slurm.conf 从哪下手的开发者。2. 环境搭建Ubuntu 18.04 上把 Vina、MGLTools、Open Babel 串成一条 PATH 链2.1 依赖清单每个包都在给某个组件补依赖MGLTools 1.5.6 这个版本是 Python2 Tk OpenGL 时代的产物install.py会现场编译几个 C 扩展缺任何一个头文件都直接失败。libxt-dev、libglu1-mesa-dev、libxmu-dev、libxi-dev是给 AutoDockTools 的 GUI 和它依赖的 Togl 组件提供 X11/OpenGL 头文件——哪怕你只打算跑命令行脚本编译阶段照样会去找X11/Xlib.h。libpng-dev、libjpeg-dev、libtiff-dev是给 PIL 用的csh是因为 MGLTools 里还残留一批 csh 脚本python-tk提供 tkinterpython-pmw是 AutoDockTools 界面用的组件库python-numpy处理坐标矩阵python-dev提供Python.h。还有一条隐性依赖Ubuntu 18.04 里python默认指向 2.7这恰好是这套老工具需要的东西。如果你的机器上装了某个科学计算发行版并把它的 bin 目录放到了 PATH 前面python install.py会直接抛SyntaxError: Missing parentheses in call to print第一眼看像安装包坏了其实就是解释器不对。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 # Open Babel 直接走 apt2.4.x 在这个流程里完全够用 sudo apt-get install -y openbabel obabel -Vobabel -V能打出类似2.4.1的版本号就说明转换器就位。有人习惯源码编译 3.x其实这条链路里只用到 sdf↔mol2、pdbqt↔sdf 这几组转换2.4 足够别为了版本号给自己堆一堆编译依赖。2.2 目录约定工具装本地盘工作目录收在 /vina单机阶段工具放哪都行一旦上集群路径就必须三个节点完全一致因为作业脚本里写的是绝对路径。我一般把工具装在本地盘的/opt/dock每个节点各一份跟着镜像走把受体、配体、脚本、结果这些「会变的东西」放在 NFS 共享的/vina上。这样脚本改一次三个节点看到的是同一份不用挨个同步。sudo mkdir -p /opt/dock cd /opt/dock # 解压 Vina 预编译包里面就是 bin/vina 一个可执行文件 sudo tar -xzf autodock_vina_1_1_2_linux_x86.tgz # MGLTools 需要跑一次安装脚本过程中会让你确认 license sudo tar -xzf mgltools_x86_64Linux2_1.5.6.tar.gz cd mgltools_x86_64Linux2_1.5.6 sudo python install.py装完先做两件检查。Vina 的预编译二进制对系统库比较挑用ldd看有没有悬空依赖ldd /opt/dock/autodock_vina_1_1_2_linux_x86/bin/vina | grep -i not found /opt/dock/autodock_vina_1_1_2_linux_x86/bin/vina --version第一条没有输出、第二条打出AutoDock Vina 1.1.2才算干净。MGLTools 那边看MGLTools-1.5.6/bin/pythonsh在不在——这个文件是 MGLTools 自带的解释器包装后面Utilities24目录下的所有脚本都靠它启动。2.3 三行 PATH 解决的是三个不同目录批量脚本开头那三行export PATH看着像模板其实每一行都指着不同的东西# vina 可执行文件 export PATH/opt/dock/autodock_vina_1_1_2_linux_x86/bin:$PATH # MGLTools 的 pythonsh 和 adt 等入口 export PATH/opt/dock/mgltools_x86_64Linux2_1.5.6/bin:$PATH # prepare_receptor4.py / prepare_ligand4.py 所在目录 export PATH/opt/dock/mgltools_x86_64Linux2_1.5.6/MGLToolsPckgs/AutoDockTools/Utilities24:$PATH第三行最关键也最容易被漏。Utilities24下的脚本第一行是#!/usr/bin/env pythonsh所以脚本里必须直接写prepare_ligand4.py -l ...让系统通过 PATH 找到pythonsh再由它解释执行。如果自作聪明写成python prepare_ligand4.py用系统 python 去加载 MGLTools 的包导入阶段就会失败报一堆No module named。还有一个必须记住的点这三行export只对当前 shell 生效。sbatch提交出去的作业是另一套环境不继承你登录时的 PATH作业脚本里要把这三行原样再写一遍。这一点在后面改并行脚本时会反复遇到。3. vina.sh 拆解一个批量对接脚本从 sdf 到 output.sdf 的完整链路3.1 受体准备只做一次别放进循环prepare_receptor4.py干三件事读 PDB、检查并补全原子类型、输出带 AutoDock 原子类型和电荷的 pdbqt。它不是给「每个配体跑一遍」用的整个任务里只该执行一次。# -r 输入受体 PDB-o 输出 pdbqt # -A hydrogens 让 AutoDockTools 补极性氢 # -e 删除非标准残基水、离子、多数杂原子 prepare_receptor4.py -r pro.pdb -A hydrogens -e -o receptor.pdbqt参数里最需要斟酌的是-e。它会清掉所有非标准残基好处是避免 pdbqt 里出现 Vina 不认识的原子类型导致直接报错坏处是如果你的活性口袋依赖某个结构水或者金属离子做桥接删掉之后对接结果就没有参考价值了。判断方法很土但有效打开原始 PDB 看结合位点周围 5 Å 内有没有 HOH 或金属有就老老实实手动挑出来保留别一删了之。准备完抽查一下grep -c ^ATOM receptor.pdbqt和原 PDB 的原子数量级应该对得上head -3 receptor.pdbqt看第一列是不是ATOM、最后一列是不是 AutoDock 原子类型A/C/N/O/HD 之类。3.2 配体转换obabel 分两步走-m是关键配体这边要做的是把「一个多分子 SDF」拆成「一堆单分子 mol2」。分两步做比一步到位好处多——中间结果能检查。# 第一步整个 SDF 转成一个多分子 mol2内容是首尾相接的多个分子块 obabel -isd testset.sdf -omol2 -O testset.mol2 # 第二步-m 表示按分子拆分输出 vs1.mol2、vs2.mol2、vs3.mol2 ... obabel testset.mol2 -O vs.mol2 -m-i和-o显式指定输入输出格式-O指定文件名-m才是拆分开关。拆分后的文件名是vs1.mol2、vs2.mol2这样的序号和原始 SDF 里的分子名没有任何关系。这一点在做结果汇总时非常致命你最后拿到的output.sdf里全是序号对不回化合物库的 ID。稳妥的做法是在拆分后立刻生成一份序号 - 原始名称的映射表存下来后面写 CSV 时用得上。另外注意电荷。obabel 从 sdf 转 mol2 默认不重新计算电荷而prepare_ligand4.py会按 AutoDock 的类型规则重新赋电荷。如果配体里带形式电荷羧酸根、季铵盐之类转换后随手抽一个看TRIPOSATOM段的电荷列是不是合理值比跑到一半再回头查省事得多。3.3 主循环靠「固定文件名」把 conf.txt 保住循环体是整个脚本的核心写得很朴素cd mols for mol2 in *.mol2 do # 配体预处理统一输出成 ligand.pdbqt prepare_ligand4.py -l $mol2 -o ligand.pdbqt -A hydrogens # 对接--cpu 1 表示只用单核 vina --config ../conf.txt --cpu 1 --out out.pdbqt --log log.txt # pdbqt 转 sdf一个 pdbqt 里的多个 MODEL 会变成 sdf 里的多个分子 obabel -ipdbqt out.pdbqt -osd -O temp.sdf cat temp.sdf output.sdf # 清掉中间文件避免下一轮互相干扰 rm -f log.txt ligand.pdbqt out.pdbqt temp.sdf done cd ..这段代码里有两个设计值得说。第一个是「固定文件名」。conf.txt里写的是ligand ligand.pdbqt所以循环里每个配体都必须输出成同一个名字靠覆盖来完成输入切换。看着土但它让conf.txt只需要维护一份——配体有八百个也不用生成八百份配置。批量脚本里这是最省事、也最不容易出错的做法。第二个是--cpu 1。单机跑的时候这个值可以设成物理核数Vina 自己会开多线程但一旦上了调度器一个作业占一个核让 Vina 再去抢多核就是跟 Slurm 对着干节点负载会莫名其妙飙高。for mol2 in *.mol2也别换成for mol2 in ls *.mol2后者遇到文件名带空格就直接崩这种低级问题在批量任务里排查起来特别费时间。3.4 conf.txt盒子定在哪比调什么参数都重要配置文件就这么十来行receptor receptor.pdbqt ligand ligand.pdbqt center_x 12.480 center_y -3.215 center_z 18.902 size_x 22 size_y 22 size_z 22 exhaustiveness 8 num_modes 9 energy_range 3 seed 20240101参数含义常见取值与说明center_x/y/z搜索盒中心坐标从共晶配体几何中心算或活性残基 Cα 质心size_x/y/z盒子边长Å20~25 之间小于 18 容易把口袋切掉一半exhaustiveness搜索穷尽程度默认 8调到 16 结果更稳但时间翻倍num_modes输出构象数默认 9写进 output.sdf 的就是这么多energy_range构象能量跨度默认 3 kcal/mol只保留接近最优的构象seed随机种子不写就用时间戳写死才能复现盒子中心怎么定是新手最容易翻车的地方。最靠谱的是找共晶配体如果原始 PDB 里带着共结晶的小分子直接算它的几何中心误差最小。没有共晶结构就退一步把文献里报道的关键残基挑出来算 Cα 质心再把盒子边长放大到 24 Å 兜住整个口袋。拿 MGLTools 的图形界面画盒子当然也行但它需要在有 X11 转发的环境里跑集群上一般不具备条件还是命令行算坐标更实际。seed这一项强烈建议写死。Vina 不写 seed 时用系统时间初始化随机数同一批分子跑两次能量值会有零点几的波动做复现实验或者跟别人对结果时这点差异足够让你怀疑人生。3.5 结果长什么样怎么快速判断有没有跑歪每轮会生成一个log.txt内容形如mode | affinity | dist from best mode | (kcal/mol) | rmsd l.b.| rmsd u.b. ------------------------------------- 1 -7.3 0.000 0.000 2 -6.9 1.412 2.038第一行mode 1的 affinity 就是这次对接的评分负得越多结合越可能强。output.sdf里每个配体会对应num_modes个构象顺序就是 mode 顺序所以取第一个分子块就是最优构象。一个必须强调的细节output.sdf用的是追加。如果不清空直接重跑第二次的结果会接着上一次往下写文件里就成了两批数据的混合体后续分析全乱。跑之前老老实实rm -f output.sdf或者干脆给每次运行建一个带时间戳的目录。4. Slurm 落地munge、slurmctld、slurmd 三件套与 slurm.conf 关键字段4.1 先让 munge 通再谈 Slurmmunge 是 Slurm 的认证组件节点之间所有 RPC 都靠它签名。它有两个硬性要求所有节点共享同一个 key 文件且各节点时间必须同步差超过几分钟就会认证失败。apt-get install -y munge libmunge-dev # 在 node01 上生成 key再 scp 到另外两台注意权限 dd if/dev/urandom bs1 count1024 of/etc/munge/munge.key chown munge:munge /etc/munge/munge.key chmod 400 /etc/munge/munge.key systemctl enable --now munge systemctl status munge # 本地自测 munge -n | unmunge | grep STATUSSTATUS: Success (0)说明本地服务正常。跨节点验证更重要在 node01 上执行ssh node02 munge -n | unmunge如果这句能通说明 key 和时间都没问题如果不通先systemctl status chrony看时间同步再md5sum /etc/munge/munge.key对比三台机器的 key 是否一致。munge 不通的情况下sinfo会一直报「Unable to contact slurm controller」你会在 slurm.conf 上白折腾半天。4.2 slurm.conf真正需要改的只有十几行先装包。Ubuntu 18.04 里slurm-wlm会把slurmctld、slurmd一起带上单独装后面两个也行但没必要。apt-get update apt-get install -y slurm-wlm slurmd slurmctld这里有个判断要做原文里还装了mariadb-server和libmysqlclient-dev那是为了 Slurm 的数据库记账slurmdbd。如果你只想先把批量对接跑起来完全不用碰数据库——把AccountingStorageType和JobCompType都设成none作业照样调度只是没有sacct历史记录。等真的需要统计资源使用量了再补 slurmdbd能省掉一大段和数据库连接的纠缠。配置文件按节点拓扑写三个节点各一份内容除节点名和地址外完全一致ClusterNamedockcluster ControlMachinenode01 ControlAddr192.168.1.11 SlurmUserroot SlurmctldPort6817 SlurmdPort6818 SlurmctldPidFile/var/run/slurm-llnl/slurmctld.pid SlurmdPidFile/var/run/slurm-llnl/slurmd.pid StateSaveLocation/var/lib/slurm-llnl/slurmctld SlurmdSpoolDir/var/spool/slurm/d AuthTypeauth/munge CryptoTypecrypto/munge ProctrackTypeproctrack/pgid TaskPlugintask/none SwitchTypeswitch/none MpiDefaultnone SelectTypeselect/linear SchedulerTypesched/backfill ReturnToService1 SlurmctldTimeout120 SlurmdTimeout300 SlurmctldLogFile/var/log/slurm-llnl/slurmctld.log SlurmdLogFile/var/log/slurm-llnl/slurmd.log SlurmctldDebug3 SlurmdDebug3 NodeNamenode01 NodeAddr192.168.1.11 CPUs1 CoresPerSocket1 ThreadsPerCore1 NodeNamenode02 NodeAddr192.168.1.12 CPUs1 CoresPerSocket1 ThreadsPerCore1 NodeNamenode03 NodeAddr192.168.1.13 CPUs1 CoresPerSocket1 ThreadsPerCore1 PartitionNamep1 Nodesnode01 DefaultYES MaxTimeINFINITE StateUP PartitionNamep2 Nodesnode02 DefaultYES MaxTimeINFINITE StateUP PartitionNamep3 Nodesnode03 DefaultYES MaxTimeINFINITE StateUP字段作用踩坑点ControlMachine控制节点主机名Slurm 19.05 之后改成 SlurmctldHost写错不生效SlurmUser运行守护进程的身份设 root 省事但 NFS 那边要配 no_root_squashStateSaveLocation作业状态持久化目录目录不存在slurmctld 直接起不来SelectType资源选择插件linear 表示整机分配是 17.11 时代的默认ProctrackType进程追踪方式pgid 最简单不需要额外内核组件SchedulerType调度策略backfill 允许小作业插队吞吐更好ReturnToService节点恢复策略设 1 后节点重启会自动回到可用状态版本差异这一条值得单独提醒。Ubuntu 18.04 仓库里的 Slurm 是 17.11 系列用ControlMachine如果你后面升级到 19.05 以上这个字段被SlurmctldHostnode01取代写成老字段会被忽略表现是控制器监听在一个你没想到的地址上。判断依据很简单slurmctld -V看版本再对着版本改字段名。CPUs1也别照抄。这个值是节点实际可分配的 CPU 数写小了浪费核写大了调度器会把多个作业塞到一个核上跑起来互相拖慢。用nproc看实际核数再填。4.3 目录、日志与开机自启Slurm 对目录很敏感路径写进配置就必须真实存在否则守护进程启动即退出。mkdir -p /var/spool/slurm/d mkdir -p /var/lib/slurm-llnl/slurmctld mkdir -p /var/log/slurm-llnl systemctl enable slurmd slurmctld systemctl start slurmd slurmctld systemctl status slurmctld --no-pager起不来先看日志不要靠猜journalctl -u slurmctld -n 50 --no-pager最常见的两条是Failed to initialize slurmctld目录缺失或权限不对和Unable to contact munge4.1 那步没通。还有一个容易自我怀疑的点配置到底读的是哪个文件。Ubuntu 的 deb 包默认读/etc/slurm-llnl/slurm.conf有些文档写的是/etc/slurm/slurm.conf用systemctl cat slurmctld | grep ExecStart看一眼启动参数里的-f指向哪里比自己纠结快得多。4.4 三节点与 NFS/vina 必须是同一份三个节点各自装好工具之后「工作目录」必须共享否则作业被调度到 node02 时找不到配体文件。NFS 是最省事的做法。# node01 上装服务端 apt-get install -y nfs-kernel-server mkdir -p /vina echo /vina 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash) /etc/exports exportfs -ra # node02 / node03 上挂载 apt-get install -y nfs-common mount -t nfs 192.168.1.11:/vina /vina df -h /vinano_root_squash这个选项是配合SlurmUserroot用的不加的话客户端以 root 身份写文件会被映射成匿名用户结果就是作业跑完了但output.sdf写不进去报Permission denied。挂载顺序也要注意先挂载再往/vina里放数据否则挂载会被本地目录覆盖你之前拷进去的文件「消失」实际上是被盖在挂载点下面了。4.5 第一个作业先验证调度链路再谈并行对接别一上来就投对接任务。先用一个两行的作业确认 sbatch → slurmd → 输出文件这条链路是通的。#!/bin/bash #SBATCH -o job.%j.out #SBATCH -p p1 #SBATCH -J myFirstJob #SBATCH --nodes1 #SBATCH --ntasks-per-node1 hostname sleep 10sbatch job1.sh提交后用这几个命令观察squeue # 看作业状态 R 运行 / PD 排队 sinfo # 看分区和节点的 State 是否 UP scancel 12 # 取消作业号 12 cat job.12.out # 看输出应该是 node01sinfo里节点如果是down或drain用sinfo -R看原因——多数是 slurmd 没起来或者 munge 认证失败。这一步过了才说明从那台机器到那个节点的作业投递是通的后面并行的所有问题都可以排除掉调度层面的嫌疑。把原来的串行脚本改造成作业脚本只需要在顶部加 SBATCH 指令、把原来的循环体包进去#!/bin/bash #SBATCH -o job.%j.out #SBATCH -p p1 #SBATCH -J dock_p1 #SBATCH --nodes1 #SBATCH --ntasks-per-node1 # 作业环境不继承登录 shell 的 PATH三行必须重写 export PATH/opt/dock/autodock_vina_1_1_2_linux_x86/bin:$PATH export PATH/opt/dock/mgltools_x86_64Linux2_1.5.6/bin:$PATH export PATH/opt/dock/mgltools_x86_64Linux2_1.5.6/MGLToolsPckgs/AutoDockTools/Utilities24:$PATH cd /vina/work/p1/mols for mol2 in *.mol2 do prepare_ligand4.py -l $mol2 -o ligand.pdbqt -A hydrogens vina --config ../conf.txt --cpu 1 --out out.pdbqt --log log.txt obabel -ipdbqt out.pdbqt -osd -O temp.sdf cat temp.sdf output.sdf rm -f log.txt ligand.pdbqt out.pdbqt temp.sdf done配体按三份拆到p1、p2、p3三个目录三个作业各占一个分区同时跑整体耗时理论上降到三分之一。拆分可以很粗糙i0 for f in /vina/work/mols/*.mol2 do case $((i % 3)) in 0) mv $f /vina/work/p1/mols/ ;; 1) mv $f /vina/work/p2/mols/ ;; 2) mv $f /vina/work/p3/mols/ ;; esac i$((i1)) done5. 避坑排查从装到跑五个最耗时间的坑5.1 安装期的两个坑第一个python install.py报SyntaxError: Missing parentheses in call to print。现象是解压、进入目录、执行安装脚本第一屏就刷一堆语法错误看起来像安装包损坏。原因不是包坏了是python这个命令指向了 Python 3——MGLTools 1.5.6 的安装脚本和它的大部分工具都是 Python 2 写的print xxx这种写法在 3 里是语法错误。解决方式是显式用 2.7python2.7 install.py同时检查which python和echo $PATH如果前面挂着某个科学计算发行版的 bin 目录要么临时从 PATH 里摘掉要么用绝对路径调用/usr/bin/python2.7。装完之后所有Utilities24下的脚本也走pythonsh不要再拿系统 python 去调。第二个prepare_receptor4.py报Could not find atomic number for ...。现象是受体 PDB 里某个原子常见的是金属离子、修饰残基、或者原子名带撇号的特殊原子在 AutoDock 的原子类型表里查不到脚本处理到那儿就停。原因有两类一类是 PDB 文件里原子名不规范比如CA在蛋白质里是 α 碳在某些配体里是钙另一类是残基本身不在标准列表里。解决方式是先加-e把非标准残基删掉试试能过就说明是老残留物不能过就把报错的那几行从 PDB 里手动抠出来看原子名和残基名必要时用obabel -ipdb x.pdb -opdb -O y.pdb重新规整一遍。5.2 单机运行期的两个坑第三个循环跑到某个配体prepare_ligand4.py直接退出提示缺TRIPOSATOM或原子数为 0。现象很突然前面几十个都好好的就某一个崩。原因是obabel -m拆出来的某个 mol2 本身就是坏的——原 SDF 里那个分子可能只有坐标没有键信息或者带了个 obabel 无法识别的键类型转换时静默产生了空分子块。解决方式是在拆分后加一步体检把异常文件提前挑出来# mol2 里 ATOM 行数少于 3 的基本都是坏分子先剔出去 for f in vs*.mol2 do n$(grep -c ^ *[0-9]* .* $f) [ $n -lt 3 ] echo suspect: $f done更省事的做法是在主循环里对prepare_ligand4.py的返回码做判断失败就跳过并记本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑