I am building a parent script which will call three scripts internally and i would like to run them in sequence manner, i.e. once previous script is successful then only i need to proceed with next else need to fail. I am running in bash mode and flavour is sun
main_script.sh
sh -x script1.sh > script1.log
status=$?
if [ $status -ne 0 ]; then
echo "Failed due to some reason"
exit 1
fi
sh -x script2.sh > script2.log
status=$?
if [ $status -ne 0 ]; then
echo "Failed due to some reason"
exit 1
fi
sh -x script3.sh > script3.log
status=$?
if [ $status -ne 0 ]; then
echo "Failed due to some reason"
exit 1
fi
I need to better solution to handle this and also i would require if rerun the main_script.sh then the those scripts which are executed successfully shouldn't execute once again. Like for eg. if script2.sh failed and if i run the main script i shouldn't run script1.sh rather than stating the message like script1 already completed hence proceeding with script2.sh
There are a lot of pieces here that don't quite seem to fit. I assume that when you say "the flavour is sun" you mean that you are running an old system from Sun Microsystems, Inc. If that is true, then you are running script1.sh , script2.sh , and script3.sh with an old Bourne shell; not with bash .
Assuming that this script is being run by bash or ksh (or some other shell that includes POSIX standard arithmetic substitutions; which does not include /bin/sh on Solaris 10 systems), the following untested code might do what you want:
[ -f status ] || date '+0 %c' > status
read job datestamp < status
if [ $job -eq 0 ]
then if sh -x script1.sh > script1.log
then job=$((job + 1))
date "+$job %c" > status
else echo "Failed due to some reason"
exit 1
fi
fi
if [ $job -eq 1 ]
then if sh -x script2.sh > script2.log
then job=$((job + 1))
date "+$job %c" > status
else echo "Failed due to some reason"
exit 2
fi
fi
if sh -x script3.sh > script3.log
then job=0
date "+$job %c" > status
else echo "Failed due to some reason"
exit 3
fi
although it is totally untested. It assumes that you always run this script in the same directory and uses a file named status in that directory to keep track of the last job that was successfully completed (and when that job last completed successfully).
I hope this gives you some idea of how you could approach this problem and gives you something you can modify to get what you want to work in your environment.
for i in 1 2 3;
do SNAM="script$i"
if [ ! -s "$SNAM.log" ]
then if ! sh -x $SNAM.sh &> $SNAM.log
then mv $SNAM.log $SNAM.err
echo "Error in $SNAM.sh"
exit $i
fi
else echo "$SNAM.log exists - script NOT rerun."
fi
done
In your case if i rerun the main_script the first script also exuecuting when script2.sh has failed. In my status i can see 1 but since you are using below code its getting replaced
From your post #6 it sounds like you found the problem, but for the record, the code I suggested should work as explained below...
The first time you run that script (or if the file status does not exist), the above statement creates a status file initialized saying that step 0 has been completed. When script1.sh completes successfully, the statements:
then job=$((job + 1))
date "+$job %c" > status
increment job to 1 and rewrites the status file to contain that 1 and the current date and time stamp.
If script2.sh then fails, the script will exit without further updating the contents of status . The next time you start the script (as long as you haven't removed status and you run it in the same directory), the statement:
[ -f status ] || date '+0 %c' > status
will find that the file status already exists so it will not update its contents and the following read statement:
read job datestamp < status
will set job to 1 . And since the following test:
if [ $job -eq 0 ]
will find that 1 is not equal to 0 , the following code to run test1.sh will not be run again until script2.sh and script3.sh have both run successfully (or you manually remove the file status or run it in a different directory).
With the status file it is harder to compute the next job.
Don's approach has it hard-coded, this is inflexible in case you want to add or remove a job(-script).
The following uses a status file and an array that allows to compute the next token, and one can simply add or remove job(-script)s.
#!/bin/bash
statusf=./status
jobs=( script1.sh script2.sh script3.sh )
njobs=${#jobs[@]}
[ -f $statusf ] || echo 0 > $statusf
read istart < $statusf
i=$istart
while :
do
echo "Running ${jobs}"
sh -x ${jobs} > ${jobs%.*}.log
status=$?
if [ $status -ne 0 ]
then
echo "failed with exit $status"
echo $i > $statusf
exit 1
fi
i=$(( (i+1) % njobs ))
# true circular behavior:
#[ $i -eq $istart ] && break
# stop after the last job in jobs[]:
if [ $i -eq 0 ]
then
echo 0 > $statusf
break
fi
done
Sorry to come with addional requirement in same thread. I need to check for a triggering file say trigger_20170801(which is in YYYYMMDD) to trigger the subsequent scripts. Basically i would require to watch the file in particular directory before the start of the main_script in next day.
To be clear
main_Script.sh is scheduled everday 10:00PM
i need to check for the trigger file till 09:00 PM next day.
if i find the trigger file then proceed with script1.sh and so on
at the successful execution i will make the file as trigger_20170801_success else trigger_20170801_failed
At next day run i will check if success file present for that month i will just come out of the main script stating already completed for this month. If failed file present then exit stating failed for this month.
Using same approach of Don
echo "Checking for trigger file"
while true;
do
if [ !-f $trigger_dir/trigg]
do
sleep 10
else
if [ -f $trigger_dir/trigg_success ]
then
echo "Previous run already completed"
exit 0;
fi
[ -f status ] || date '+0 %c' > status
read job datestamp < status
if [ $job -eq 0 ]
then if sh -x script1.sh > script1.log
then job=$((job + 1))
date "+$job %c" > status
else echo "Failed due to some reason"
mv $trigger_dir/trigg > $trigger_dir/trigg_failed
exit 1
fi
fi
if [ $job -eq 1 ]
then if sh -x script2.sh > script2.log
then job=$((job + 1))
date "+$job %c" > status
else echo "Failed due to some reason"
mv $trigger_dir/trigg > $trigger_dir/failed
exit 2
fi
fi
if sh -x script3.sh > script3.log
then job=0
date "+$job %c" > status
mv $trigger_dir/trigg > $trigger_dir/trigg_success
else echo "Failed due to some reason"
mv $trigger_dir/trigg > $trigger_dir/trigg_failed
exit 3
fi
fi
done
I need to validate for that month run trigger file and act. Also check for the trigger file till 09:00 PM next day