如何在Compute Canada的SBATCH脚本中用Trap保存SLURM_TMPDIR文件
问题
在Compute Canada中使用SLURM_TMPDIR执行密集型I/O操作(如克隆大型代码仓库、分析提交历史)时,作业超出分配时间后,SLURM_TMPDIR内的输出文件会丢失。尝试用信号陷阱解决,但现有脚本无法捕获信号,甚至连Moving File都没打印,无法将文件复制到指定位置。原脚本如下:
#!/bin/bash #SBATCH --mem=128G #SBATCH --nodes=1 #SBATCH --ntasks-per-node=8 #SBATCH --time=0:10:0 #SBATCH --signal=B:SIGUSR1@120 output_file_name=file_0000.jsonl echo "Start" function handle_signal() { echo 'Moving File' cp $SLURM_TMPDIR/<output_file_path> <my_compute_canada_directory> exit 2 } trap 'handle_signal' SIGUSR1 cd $SLURM_TMPDIR git clone ... cd ... module purge module load java/17.0.2 module load python/3.10 export JAVA_TOOL_OPTIONS="-Xms256m -Xmx5g" python -m venv res_venv source .venv/bin/activate pip install -r requirements.txt python data_collector.py ./data/file_0000.csv $output_file_name wait echo "Test" exit 0
解决方案
1. 修正信号陷阱的核心问题
SLURM的--signal=B:SIGUSR1@120表示在作业结束前120秒向bash主进程发送信号,但原脚本存在两个关键问题:
- 占位符路径未替换:
$SLURM_TMPDIR/<output_file_path>是无效路径,需替换为实际输出文件的绝对路径 - 陷阱触发时机:确保
trap命令在所有任务执行前设置,避免脚本运行到一半才绑定信号
2. 增强陷阱函数的鲁棒性
需要在捕获信号后,先终止Python子进程(避免文件写入不完整),再检查文件存在性后复制:
function handle_signal() { echo "收到终止信号,开始备份文件..." # 终止当前运行的Python子进程 pkill -P $$ python # 等待进程退出,确保文件写入完成 wait # 检查文件并复制,添加错误提示 if [ -f "$output_path" ]; then cp "$output_path" "$final_output_dir" echo "文件已备份到 $final_output_dir" else echo "警告:输出文件 $output_path 不存在" fi exit 2 }
3. 覆盖正常结束与超时两种场景
原脚本仅处理超时信号,需在Python脚本正常执行完成后也触发文件复制,确保两种场景下数据都能保留。
4. 补充信号捕获范围
除了SIGUSR1,建议同时捕获SIGTERM(SLURM最终终止作业时发送的信号),避免遗漏终止事件:
trap 'handle_signal' SIGUSR1 SIGTERM
修正后的完整脚本
#!/bin/bash #SBATCH --mem=128G #SBATCH --nodes=1 #SBATCH --ntasks-per-node=8 #SBATCH --time=0:10:0 #SBATCH --signal=B:SIGUSR1@120 # 定义明确的路径变量(替换为你的实际路径) output_file_name=file_0000.jsonl output_dir=$SLURM_TMPDIR final_output_dir="/home/your-username/your-target-directory" output_path="${output_dir}/${output_file_name}" echo "作业启动,临时目录:$SLURM_TMPDIR" function handle_signal() { echo "收到终止信号,开始备份文件..." # 终止Python子进程 pkill -P $$ python wait # 检查并复制文件 if [ -f "$output_path" ]; then cp "$output_path" "$final_output_dir" echo "文件备份成功:$final_output_dir/$output_file_name" else echo "错误:输出文件不存在" fi exit 2 } # 提前设置信号陷阱 trap 'handle_signal' SIGUSR1 SIGTERM # 进入临时目录 cd $SLURM_TMPDIR || { echo "无法进入SLURM_TMPDIR"; exit 1; } # 克隆仓库(替换为你的仓库地址) git clone https://your-repo-url.git # 进入项目目录(替换为实际目录) cd your-project-folder || { echo "无法进入项目目录"; exit 1; } # 加载环境模块 module purge module load java/17.0.2 module load python/3.10 # 创建并激活虚拟环境 python -m venv res_venv source res_venv/bin/activate pip install -r requirements.txt # 执行Python采集脚本 python data_collector.py ./data/file_0000.csv $output_file_name # 正常结束时复制文件 echo "作业正常完成,开始复制文件..." if [ -f "$output_path" ]; then cp "$output_path" "$final_output_dir" echo "文件复制成功:$final_output_dir/$output_file_name" else echo "错误:输出文件不存在" fi echo "作业结束" exit 0
内容的提问来源于stack exchange,提问作者not-a-bot
相关产品推荐
相关产品推荐

