В чем разница между "else if" и "elif" в bash?
У меня есть следующая оболочка script, которая должна просто скомпоновать несколько файлов Java.ear/.war в 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
В частности, раздел, который меня смущает, следующий:
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
Я не могу заставить elif [ -e hcm.war ]
корректно работать на удаленном сервере. Удаленный сервер работает bash 3.2.25 на redhat (если это имеет значение.) Я подозреваю, что мне просто не хватает какой-то придирчивой bash оболочки script detail.
Любые предложения?
Ответы
Ответ 1
Ваш код как опубликованный, кажется, работает.
Существует разница между elif .. fi
AND else ; if ... fi
. Истинный elif ... fi
будет содержать меньше fi
в конце, чем ваш код.
Ваш код, опубликованный, спрашивает: "Если hcm.ear существует, ТОГДА проверьте, есть ли hcm.war". Это то, что вы хотите? Другой логический путь к тесту будет "если hcm.ear не существует. ТОГДА проверьте, есть ли hcm.war."
Этот альтернативный логический путь выглядит как
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
Надеюсь, это поможет.
Ответ 2
Это не прямой ответ на вопрос (elif vs else), но я бы сделал рефакторинг следующим образом:
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
...
т.е. всегда пытайтесь копировать, так как вы всегда хотите их выполнять, если кто-то не выполняет попытку следующего и т.д.
В стороне, вы всегда хотите обернуть пути и строки в кавычки. В противном случае путь, содержащий пробелы, приведет к разрыву приложения.