Script execution in sequence manner

Hi guys,

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.

How about

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

HI don,

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

[ -f status ] || date '+0 %c' > status

It is most simple record the jobs to be skipped, i.e. the good jobs.
Then initially the "good" file can be empty or missing.

#!/bin/bash
good=./good
for job in script1.sh script2.sh script3.sh
do
  if [ -f $good ] && fgrep -x $job $good >/dev/null
  then
    echo "$job already completed"
  else
    echo "Running $job"
    sh -x $job > ${job%.*}.log
    status=$?
    if [ $status -ne 0 ]; then
      echo "failed with exit $status"
      exit 1
    else
      echo $job >> $good
    fi
  fi
done
echo "all good, removing $good"
rm $good

Thanks all, I corrected the error it worked Don. Thanks all for your suggestion

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).

1 Like

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
1 Like

Thanks Don and all.

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