如何在Slurm作业中定义R脚本所需的变量
在Slurm脚本中给R脚本传递变量的正确方法
你原来的Slurm脚本问题在于:执行R命令会进入R的交互式环境,后续的bash命令(包括Rscript Rscript.R)会被暂停,直到退出R才会执行,所以无法按预期运行脚本。下面是几种可行的解决办法:
方案1:命令行传递参数给R脚本
修改R脚本,通过commandArgs()获取命令行传入的参数,这样Slurm脚本直接在调用Rscript时传递变量值。
修改后的Rscript.R:
# 获取命令行末尾的参数(trailingOnly=TRUE忽略R本身的启动参数) args <- commandArgs(trailingOnly = TRUE) my.wd <- args[1] f1 <- args[2] f2 <- args[3] setwd(my.wd) x <- read.csv(f1) y <- read.csv(f2) out.df <- rbind(x, y) # 建议加上row.names=FALSE避免输出多余的行号列 write.csv(out.df, file = "out.csv", row.names = FALSE)
对应的Slurm脚本myjob.run:
#!/bin/bash #SBATCH --nodes=1 #SBATCH --ntasks=1 #SBATCH --cpus-per-task=8 #SBATCH --mem=1GB #SBATCH --time=1:00:00 module load r/4.4.2 # 直接在Rscript命令后传递参数,顺序对应R脚本中的args索引 Rscript Rscript.R "/path/to/files" "file1.csv" "file2.csv"
方案2:通过环境变量传递变量
在bash中定义环境变量,R脚本通过Sys.getenv()读取这些变量,适合需要在多个脚本间共享参数的场景。
Slurm脚本myjob.run:
#!/bin/bash #SBATCH --nodes=1 #SBATCH --ntasks=1 #SBATCH --cpus-per-task=8 #SBATCH --mem=1GB #SBATCH --time=1:00:00 module load r/4.4.2 # 定义环境变量(建议用大写区分bash变量和R变量) export MY_WD="/path/to/files" export F1="file1.csv" export F2="file2.csv" # 运行R脚本 Rscript Rscript.R
修改后的Rscript.R:
# 读取bash中定义的环境变量 my.wd <- Sys.getenv("MY_WD") f1 <- Sys.getenv("F1") f2 <- Sys.getenv("F2") setwd(my.wd) x <- read.csv(f1) y <- read.csv(f2) out.df <- rbind(x, y) write.csv(out.df, file = "out.csv", row.names = FALSE)
方案3:使用Bash Here文档(无需修改原R脚本)
如果不想改动原R脚本,可以用Bash的Here文档,先在R环境中定义变量,再source原脚本。
Slurm脚本myjob.run:
#!/bin/bash #SBATCH --nodes=1 #SBATCH --ntasks=1 #SBATCH --cpus-per-task=8 #SBATCH --mem=1GB #SBATCH --time=1:00:00 module load r/4.4.2 # 使用here文档启动R并执行命令,EOF是结束标记(可自定义,前后要一致) R --vanilla << EOF my.wd <- "/path/to/files" f1 <- "file1.csv" f2 <- "file2.csv" # 加载原R脚本,此时脚本会使用上面定义的变量 source("Rscript.R") EOF
这种方式完全保留你原来的Rscript.R代码,无需修改。
内容的提问来源于stack exchange,提问作者cfausto
相关产品推荐
相关产品推荐

