Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between "else if" and "elif" in bash?

Tags:

I've got the following shell script that's supposed to simply stage a few Java .ear/.war files to JBoss:

SUCCESS=false DEPLOY_PATH=/apps/jboss/server/default/deploy  E_NOARGS=75 M_USAGE="usage: $0 {rcm|hcm}" M_MISSING_RCM="missing: rcm.war file not present" M_MISSING_HCM="missing: hcm.ear or hcm.war file not present"  if [ -z "$1" ]  then   echo $M_USAGE   exit $E_NOARGS else   M_START="deploying $1 ..."   M_FINISH="finished deploying $1" fi  until [ -z "$1" ] do   echo $M_START    case "$1" in     rcm*)       # do a hot-deploy of the rcm.war file       # TODO: test if rcm.war file is present, error out if not       if [ -e rcm.war ]       then          cp -v rcm.war $DEPLOY_PATH/rcm.war         SUCCESS=true       else         echo $M_MISSING_RCM       fi       ;;     hcm*)       # do a shutdown, deploy hcm.war, and restart jboss       ps -ef | awk '/jboss/{print $2}' | xargs kill -s KILL        HCM_DEPLOYED=false        if [ -e hcm.ear ]       then         cp -v hcm.ear $DEPLOY_PATH/hcm.ear         HCM_DEPLOYED=true       else         if [ -e hcm.war ]         then           cp -v hcm.war $DEPLOY_PATH/hcm.war           HCM_DEPLOYED=true         else            echo $M_MISSING_HCM         fi       fi        if $HCM_DEPLOYED ;       then         # TODO: detect the hostname         nohup /apps/jboss/bin/run.sh -b <HOSTNAME> & &> /dev/null         SUCCESS=true       fi       ;;     *)       echo $M_USAGE       exit 1   esac   shift done  if $SUCCESS ; then   echo $M_FINISH fi 

The section in particular that confuses me is this one:

      if [ -e hcm.ear ]       then         cp -v hcm.ear $DEPLOY_PATH/hcm.ear         HCM_DEPLOYED=true       else         if [ -e hcm.war ]         then           cp -v hcm.war $DEPLOY_PATH/hcm.war           HCM_DEPLOYED=true         else            echo $M_MISSING_HCM         fi       fi 

I can't seem to get elif [ -e hcm.war ] to work correctly on the remote server. The remote server is running bash 3.2.25 on redhat (if that makes any difference.) I suspect I'm just missing some picky bash shell script detail.

Any suggestions?

like image 233
emptyset Avatar asked Aug 19 '11 19:08

emptyset


2 Answers

Your code as posted seems to work.

There is a difference between elif .. fi AND else ; if ... fi. A true elif ... fi will have one fewer fi at the end than your code.

Your code as posted, asks, "if hcm.ear exists THEN check if there is an hcm.war". Is that what you want? The other logic path to test would be "if hcm.ear doesn't exist THEN check if there an hcm.war."

That alternate logic path looks like

  if [ -e hcm.ear ] ; then     cp -v hcm.ear $DEPLOY_PATH/hcm.ear     HCM_DEPLOYED=true   elif [ -e hcm.war ] ; then       cp -v hcm.war $DEPLOY_PATH/hcm.war       HCM_DEPLOYED=true   else      echo $M_MISSING_HCM   fi 

I hope this helps.

like image 191
shellter Avatar answered Oct 21 '22 19:10

shellter


This isn't a direct answer to the question (elif vs else) but I would refactor like so:

HCM_DEPLOYED=true cp -v hcm.ear "${DEPLOY_PATH}/" || cp -v hcm.war "${DEPLOY_PATH}/" || HCM_DEPLOYED=false if [ ! ${HCM_DEPLOYED} ]; then    echo "${M_MISSING_HCM}" else     # TODO: detect the hostname     ... 

I.e. always try the copies since you always want to do them, if one fails try the next, etc.

As an aside, you always want to wrap paths and strings in quotes. Otherwise a path containing spaces will cause your app to break.

like image 35
Paul Hargreaves Avatar answered Oct 21 '22 17:10

Paul Hargreaves