我觉得你的问题是,SAS试图将日志文件写入到您没有写入权限的目录。您可以将该日志文件(和.out文件)的备用位置传递给SAS:
sas_log <- tempfile()
sas_out <- tempfile()
cmd <- sprintf(
'sas.exe -nosplash -icon -sysin "%s" -log "%s" -print "%s"',
sas_script, sas_log, sas_out
)
return_code <- system(cmd) # Runs sas and saves the return code to
我认为这应该可以解决您的问题。您可能需要将您的日志文件放在与SAS脚本产生的任何结果相同的位置,而不是在一个不明确的临时目录中。
高级示例:
我曾经写过的包装功能的SAS脚本,其中包括记录和错误处理。也许这是对你有用,但你将不得不稍作修改,使其在系统上运行:
library(futile.logger)
library(purrr)
library(assertthat)
library(stringi)
library(magrittr)
sasget <- function(
infile,
outfile = NULL,
sas_script,
sas_path = "C:/Program Files/SAS/x86/SASFoundation/9.4",
sas_config = "C:/Program Files/SAS/x86/SASFoundation/9.4/nls/de/sasv9.cfg"
){
# Precondtions
assert_that(purrr::is_scalar_character(infile))
assert_that(is.null(outfile) || purrr::is_scalar_character(outfile))
assert_that(file.exists(sas_script))
assert_that(dir.exists(sas_path))
assert_that(file.exists(sas_config))
# Process arguments
if(is.null(outfile)) outfile <- tempfile()
sas_log <- paste0(outfile, '.log')
sas_out <- paste0(outfile, '.lst')
# Launch sas job
owd <- getwd()
setwd(sas_path)
on.exit(setwd(owd), add = TRUE)
cmd <- sprintf(
'sas.exe -nosplash -icon -sysin "%s" -set filein "%s" -set fileout "%s" -log "%s" -print "%s"',
sas_script, infile, outfile, sas_log, sas_out)
flog.debug('Launching SAS job')
flog.trace(cmd)
return_code <- shell(cmd) # Run SAS and retain return code
# Process SAS Log
log <- suppressWarnings(try(readLines(sas_log), silent = TRUE))
errors <- log %>%
stringi::stri_subset_regex('^ERROR.*:')
lapply(log, flog.trace)
# Postconditions
ok <- TRUE
if(!identical(return_code, 0L)){
flog.error('SAS process returned nonzero return code: %s', return_code)
ok <- FALSE
}
if(isTRUE(file.size(outfile) == 0L)){
flog.error('SAS process returned empty file')
ok <- FALSE
}
if(length(errors) > 0L){
lapply(errors, flog.error)
ok <- FALSE
}
if(ok){
flog.debug('SAS file transfer successful')
} else {
flog.fatal('There were Errors, please check SAS log: %s', sas_log) %>%
stop()
}
# output
res <- outfile
return(res)
}
注:
- ,我不得不删除一些代码块包含具体针对我希望我没有留下任何让人困惑的项目。
- 我将参数
infile
和outfile
作为如何将宏变量传递给SAS脚本的示例。您可以像这样在SAS脚本中使用它们:%let fileIn = %sysget(filein)
。
您的代码是否从命令行工作,即执行SAS代码的系统命令? – Reeza
您可能希望查看'processx'作为'system'和'system2'的替代方案 –