I am using R to execute a sas program following Dominic Comtois's approach (Executing a SAS program in R using system() Command). When I executed my test codes, a error massage showed up
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;
How to resolve this issue. Any help will be highly appreciated.
Yong
I think your problem is that SAS tries to write a logfile to a directory where you have no write access. You can pass an alternate location for that log file (and the .out file) to 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
I think this should solve your problem. You will probably want your log file in the same location as whatever result your SAS script produces, and not in a obscure temporary directory.
Advanced Example:
I once wrote a wrapper function for a SAS script that includes logging and error handling. Maybe this is useful to you, but you will have to modify it a bit to make it run on your system:
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)
}
Notes:
- I had to remove some code chunks that were specific to the project I was working on, I hope i didn't leave anything confusing in.
- I left the parameters
infile
and outfile
in as an example of how to pass macro variables to a SAS script. You can use them in your SAS script like this: %let fileIn = %sysget(filein)
.