2017-08-14 66 views
1

我使用R来执行一个遵循Dominic Comtois的方法(Executing a SAS program in R using system() Command)的sas程序。当我执行我的测试代码,一个错误按摩露面使用shell函数从r运行sas

ERROR: Insufficient authorization to access C:\Program Files\SASHome\x86\SASFoundation\9.3\test_YL.log. 

My test sas program was: 

    libname XX 'F:/sitetools'; 
    data XX.test; 
    input species $ bec_i_c $ agetype age height; 
    cards; 
    FD C 1 35 14.3 
    FD C 0 35 14.3 
    FD I 1 35 14.3 
    FD I 0 35 14.3 
    PL I 1 65 14.3 
    PL I 1 25 14.3 
    PL I 0 65 14.3 
    PL I 0 25 14.3 
    ; 
    run; 

如何来解决这个问题。任何帮助将不胜感激。

+0

您的代码是否从命令行工作,即执行SAS代码的系统命令? – Reeza

+0

您可能希望查看'processx'作为'system'和'system2'的替代方案 –

回答

1

我觉得你的问题是,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) 
} 

注:

  • ,我不得不删除一些代码块包含具体针对我希望我没有留下任何让人困惑的项目。
  • 我将参数infileoutfile作为如何将宏变量传递给SAS脚本的示例。您可以像这样在SAS脚本中使用它们:%let fileIn = %sysget(filein)
+0

您是否知道如何以管理员身份从R运行sas? –