2017-08-14 101 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? –