最近写了一些 mpi 程序, 但是有 bug, 且只有在多机上能够复现. 然而因为工程太大, 编译一次需要时间比较长, 所以反复 print 也并不方便解决问题. 而且集群上也没有图形界面, ssh -X xterm 的方法不太好使. 所以需要一些新的解决思路.

laekov 将目光瞄准了 tmux. 用 tmux new-session command 就可以在目标机器上新开一个进程, 跑 gdb. 然而 tmux 并不能继承环境, 所以需要再包一层脚本来重新加载环境 (这倒是和多机跑 mpi 程序差不多). 此外, 为了不需要手工一个一个进程地去 gdb 里开始, 可以用 gdb -ex 'r' --args command args 来让它自动开跑. ex 还可以用来批处理设断点之类的, 非常方便.

另一个问题是 laekov 用的集群配置了 slurm, 是用 srun 来启程序的. 但是 tmux 命令会立即退出, 进程是跑在该用户的另一个进程里的, 而且这俩还没有父子关系, 无法用 wait 来等. 但是 srun 的进程退出之后 slurm 就认为这个进程跑完了, 甚至会清理 worker 上该用户的所有进程. 这就不太科学了. 解决方案是在主脚本里轮询 tmux has-session, 这样结束 gdb 的时候要么直接 ctrl+c 掐程序, 要么在 tmux 里面把 pane 关掉就可以了.

一个完整的 tanmux.sh 长成如下这个样子.

#!/bin/bash
tmux new-session -d ./wrapper.sh $@
hostname

while true
do
    if tmux has-session
    then
        echo $(hostname) alive at $(date)
        sleep 10s
    else
        break
    fi
done

有时候这样启进程会提示找不到 tmux 的 tmp 文件. 目前解决方案是手工 ssh 上去 tmux 一下. 可能是什么魔法问题, 之后可以再改进一下.

搞定这些事情之后, 就可以切到一个干净的 workspace, 然后开一堆 terminal 去 ssh -t tmux a 看 gdb 们跑了. 各个进程分别被显示在不同的 terminal 里面, 比糊在同一个 terminal 里清晰了不少, debug 的进度也有所增加.