Variable gets auto updated after function execution

Hi Team

In the below code, irrespective of the if statement that gets executed, retcd is being assigned a standard value(1) instead of changing as per code. Could you please help to see where is it going wrong.

rval=0
CONF_FILE=/apps/wmroot/scripts/props/UMPath.properties
NOHUP="nohup"
getProperty()
{
        prop_key=$1
        prop_file=$2
        prop_value=`cat ${prop_file} | grep ${prop_key} | cut -d'=' -f2`

}
#get properties
getProperty "value.UMPath" ${CONF_FILE}
UMPath=${prop_value}
echo "$UMPath"
# Clear any currently running tail commands which will cause the loop below to fail
ps -ef|grep -v grep|grep tail|grep $UMPath|grep nirvana.log > /dev/null
if (( $? == 0 )); then
   echo -e "\nClearing the following tail commands:"
   ps -ef|grep -v grep|grep tail|grep $UMPath|grep nirvana.log
   ps -ef|grep -v grep|grep tail|grep $UMPath|grep nirvana.log|awk '{print $2}' | xargs kill -9
fi
#Finding the nserver.pid to see if UM is up

SERVER_PID=$UMPath/bin/nserver.pid

echo "Check if UM Server is running or not"

 if [ -f $SERVER_PID ] ; then
       echo "UM Server is running.."
exit $rval
 else
        echo "UM Server is down, starting it up"
        su - wmroot -c "${NOHUP} "$UMPath/bin/nserver" &"
 fi
# Watch the log file for the initialization string
getline()
{
echo -e "\nNow watching nirvana log for the Started Nirvana Realm string\c"
tail -f $UMPath/data/nirvana.log | while read line
do
    echo ${line} | egrep "Realm Server Startup sequence completed" > /dev/null 2>&1
  if (( $? == 0 )); then
     echo -e "\nFound: ${line}\n"
echo "UM is now up and running"
retcd=0
return $retcd;
exit $retcd
  fi
 echo ${line} | egrep "Server shutdown" > /dev/null 2>&1
  if (( $? == 0 )); then
     echo -e "\nFound: ${line}\n"
echo "UM failed to start. Please check"
retcd=1
return $retcd;
exit $retcd
  fi
done
}
getline
if [ "$retcd" = 0 ]
then
echo "server is now up"
else
echo "Server has been shutdown due to an error, please check"
fi
exit $rval

Its my pleasure: let us first start with:

getline()
{
[...]
retcd=0
return $retcd;
exit $retcd
[...] 
}

These lines (the same construct is used several times) do not make any sense: return leaves the subroutine and branches back into the calling routine. So, whatever is after return , it will not be executed because execution never gets there. In this case this is lucky, by the way, because exit would leve the script completely and i doubt this is what you want.

Second:

retcd=0
return $retcd

what happens in the second line is: the shell notices that there is a variable (retcd) to expand and replaces the variables name with its content:

return 0

Only then the line is executed. You do NOT pass back a variable you pass back a variables content. Because the variable itself is local to the subroutine the calling routine will not know about the variable, therefore:

getline()
{
return $retcd;
}
getline
if [ "$retcd" = 0 ]

won't work because in the main part the variable "retcd" doesn't exist.

I haven't bothered to look for further logical errors because your script is so poorly formatted that it is hard to find out where (and if) the if s and else s and fi s all match. I suggest you reformat your code in your own interest, because this is nearly unreadable.

One more thing:

echo ${line} | egrep "Realm Server Startup sequence completed" > /dev/null 2>&1
if (( $? == 0 )); then

You obviously try to find out if a certain string contains another string. You can do that by simply:

if echo "${line}" | grep -q "Realm Server Startup sequence completed" 2>/dev/null ; then

First, you do not need egrep to search for a fixed string, second, you can use the command itself (and its return code) for if to process and lastly you do not need to redirect output when you can switch it off ("-q") before it even is produced.

I hope this helps.

bakunin

This certainly helps. I will modify my code accordingly to see if it works as expected. Thank you

grep -q might not work with all grep versions. What is your OS?

tail -f $UMPath/data/nirvana.log | while read line
do
done

Several problems with that.
The pipe forces the while-do-done block into a sub shell.

  • While the return should work an exit can produces different results, dependent on the shell. BTW what shell and OS do you use?
  • Your main problem: changes on variables are not copied back to the main shell.

Then, if the sub shell terminates, it sends a SIGPIPE to the tail -f that hopefully terminates.
The following eliminates some problems

# Watch the log file for the initialization string
getline()
{
# use the portable printf in favor of echo -e
printf "\nNow watching nirvana log for the Started Nirvana Realm string"
# tail -f will hopefully terminate
tail -f $UMPath/data/nirvana.log |
# the pipe forces the while-do-done into a sub shell:
# variables are not returned but a return value should work
while read line
do
    case "$line" in
    *"Realm Server Startup sequence completed"*)
        printf "\nFound: %s\n\n" "$line"
        return 0
    ;;
    *"Server shutdown"*)
        printf "\nFound: %\n\n" "$line"
        return 1
    ;;
    esac
done
}
# act on the return value
if getline
then
    echo "UM is now up and running"
else
    echo "UM failed to start. Please check"
    rval=1
fi
exit $rval