Link to home
Start Free TrialLog in
Avatar of labradorchik
labradorchikFlag for United States of America

asked on

How to run SAS program in Unix Bash script with checking for errors and also calling another bash script?

Hi everyone!
I am trying to do a few things in my bash script (script1.sh):  pass logicals/variables to my SAS program (program1.sas), execute SAS code (program1.sas), check for errors, write all messages to a log file (sas_program.log), and also execute another script (script2.sh) which has a few directory logicals/variables shortcuts.

Please note: variable/logicals (file1, file2, plog, and stat) are also defined in the SAS program.  

Please provide any suggestions or examples if you can.
Here is what I have so far:

#script1.sh

#!/bin/bash

#executing script2.sh script 
source script2.sh

# Creating variables for directories
export DATADIR1=/root/alldirs/2018/data1
export DATADIR2=/root/alldirs/2018/data2
export DATADIR3=/root/alldirs/2018/data3
export PROGDIR1=/root/alldirs/2018/prog1


#Creating variables for data files that are used in program1.sas and final log file 
export file1=DATADIR1/sasdata1.sas7bdat
export file2=DATADIR2/sasdata2.sas7bdat
export plog=DATADIR3/sas_program.log

#Setting stat variable for future use
stat=0

#executing SAS program, checking for errors, and writing all messages to a log file 
sas ${PROGDIR1}/program1.sas -log ${DATADIR3}program1.log
stat=$?
   if [[ "$stat" !=0 ]]; 
     then echo -e "--- Error: Abnormal end in program program1.sas. Check log file! ---" >> $plog
    exit 2
             echo -e "--- Program1.sas run successfully! ---" >> $plog
   fi
exit 0

Open in new window




Any suggestions would be appreciated!
Thank you!
ASKER CERTIFIED SOLUTION
Avatar of noci
noci

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi labradorchik,

I've got some suggestions at the more minor/microscopic level.

You've put 2 levels of indent in your "if" statement, which is not normal.  It's not traditional to indent the entire "if" statement.  I guess this is because it is logically at the same level as the surrounding code.  Just indent the statements inside the "then" and "else" blocks, as you have done, but not the entire thing.

This will give you a syntax error, because there needs to be a space after the "!=".
    if [[ $stat !=0 ]];
There is no need to have a ";" at the end of this line:
    if [[ $stat != 0 ]];
You'd only need it if you were wanting to have more things after that on the same line, e.g.:
    if [[ $stat != 0 ]]; then

Although you'd probably get away with it in this case, "!=" is for string comparison.  "-ne" is for numeric comparison.

I also don't see the need for "-e" switches in your echo statements.  Why do you have them?

And personally I'd prefer to use a positive test instead of a negative test and swap the statements inside the "then" & "else" blocks around.

So putting all that together, the last part of your code could be rewritten like:
sas ${PROGDIR1}/program1.sas -log ${DATADIR3}program1.log
stat=$?
if [[ $stat -eq 0 ]]
then 
else
  echo "--- Program1.sas run successfully! ---" >> $plog
else
  echo "--- Error: Abnormal end in program program1.sas. Check log file! ---" >> $plog
  exit 2
fi
exit 0

Open in new window

Avatar of labradorchik

ASKER

Thank you guys for your suggestions!

So, am I executing my second script (script2.sh) correctly?

Should I include the directory as well if my current script (script1.sh) is in a different directory than script2.sh?

example:
 #executing script2.sh script 
source ${PROGDIR1}/script2.sh

Open in new window


How do I know that my second script executes within my current script?
Hi labradorchik,

Looks good from this angle.
I assume you know the short-hand way of writing that with a "." instead of "source", i.e.:
    . ${PROGDIR1}/script2.sh
But using "source" makes it more obvious.

And I've just noticed that this line:
    sas ${PROGDIR1}/program1.sas -log ${DATADIR3}program1.log
should have a "/" after "${DATADIR3}", otherwise you'll be referring to "/root/alldirs/2018/data3program1.log".

And if you want to you can make the variable syntax throughout your code more concise by removing the {}, e.g.:
    sas $PROGDIR1/program1.sas -log $DATADIR3/program1.log
There are cases where you need the {}, e.g. when adjacent characters could be part of the variable name, but after the above addition of "/" I don't see that happening in your code now.  But you might like to leave them in to keep a consistent style regardless of the special cases.

And as noci has told me privately, my suggested code should not have:
    then
    else
That first "else" was a typo.  Thanks noci.
Avatar of noci
noci

The Braces {} are actualy a good form the uniquely define the name it is allways...
Consider the difference:    $BLAH33 and ${BLAH}33   the former requires the variable BLAH33 the latter append 33 to the contents of variable BLAH...
besides that with {} modifiers can be used to provide defaults...

${DIRECTORY:-/thisdir/is/default}      will use the value of DIRECTORY if present, if empty /thisdir/is/default  will be used.
${INDIR}/input.txt ${INDIR/in/out}/output.txt     # will change the ccurence of in -> out
with INDER = in_dir  translates to:  indir/intput.txt out_dir/output.txt

More modifiers exist: See man bash and search for: Parameter Expansion
> "The Braces {} are actualy a good form the uniquely define the name it is allways..."
Sorry noci, but although English is my first language, I don't understand various parts of your grammar, so I can't be sure of what you mean exactly.

> "Consider the difference:    $BLAH33 and ${BLAH}33   the former requires the variable BLAH33 the latter append 33 to the contents of variable BLAH..."
True, that's why I said 'There are cases where you need the {}, e.g. when adjacent characters could be part of the variable name, but after the above addition of "/" I don't see that happening in your code now.  But you might like to leave them in to keep a consistent style regardless of the special cases.'

> "besides that with {} modifiers can be used to provide defaults..."
True, but that is not the usage of {} that I was trying to suggest could be removed.
English definitely is NOT my first language...
Imho {} are preferable because of the extra functions and because it leaves small room for errors and misunderstandings.
Opnions may differ my background includes programming in perl, python, bash etc. so braces don't frighten me...
Using one form consistently makes one make less errors.. and we can definitely do without those.
> "Imho {} are preferable because of the extra functions and because it leaves small room for errors and misunderstandings."
I like them for the extra functions, too.  As indicated in my last post, I never tried to imply I didn't.

> "Opnions may differ my background includes programming in perl, python, bash etc. so braces don't frighten me..."
They don't frighted me either, but in the vast majority of code I've seen and written, they're just unnecessary for delimiting variable names.

> "Using one form consistently makes one make less errors.. and we can definitely do without those."
That can be true for some people, which is why I said: "But you might like to leave them in to keep a consistent style regardless of the special cases."
The special cases I was referring to were like your "${BLAH}33" example.
Thank you guys for helping me with this script!
I found the solution from noci the most valid and quick. But also I would like to say thanks to tel2 for all your suggestions and comments!

Thank you again guys!!