Wouldn't it be nice to schedule a redeployment of your updated web-app during off-peak hours AUTOMATICALLY?
I tried searching for some existing scripts or blogs on how others might have done this, but surprisingly nothing came up. So I'm sharing how I did this from scratch and I'm hoping others will find this useful.
The Bash script
The bash script is responsible for shutting down tomcat, undeploying your webapp, deploying your new web-app and starting up tomcat. The script takes in two arguments.- The name of the web-app without the '.war' extension
- The location of the new version of the web-app
# deploy.sh
# Script to shutdown tomcat and redeploy webapp
#Check the number of arguments
if [ "$#" -ne 2 ]
then
echo "Missing arguments: webapp name and WAR file location"
exit 1
fi
if [ -z "$1" ]
then
echo "First argument cannot be empty"
exit 1
fi
if [ -z "$2" ]
then
echo "Second argument cannot be empty"
exit 1
fi
tomcatHome="/usr/local/apache-tomcat-7.0.55"
echo "Tomcat home: $tomcatHome"
# Get the process ID of tomcat
pid=$(ps h -C java -o "%p:%a" | grep catalina | cut -d: -f1)
if [ "$pid" > 0 ]
then
echo "Shutting down tomcat PID $pid"
# Shutdown tomcat
#$tomcatHome/bin/shutdown.sh
kill -9 $pid
# Wait until tomcat is shutdown
while kill -0 $pid > /dev/null; do sleep 1; done
fi
# remove the old webapp
echo "Removing webapp $1"
mv $tomcatHome/webapps/$1.war $tomcatHome
rm -rf $tomcatHome/webapps/$1
# Copy the new WAR file to the webapps folder
cp $2 $tomcatHome/webapps/$1.war
# Change the permissions
chown tomcat:tomcat $tomcatHome/webapps/$1.war
# Start up tomcat
/etc/init.d/tomcat start
# Finished
echo "redeployed successfully"
An example of how to run the script:
./deploy.sh TaskRequest /home/philip/TaskRequest.war
If you plan on reusing my script, one of the things you'll most likely want to change is the 'tomcatHome' variable and the way I move copies of the old WAR file out of the web-apps folder.
Make sure that you have permissions to execute the bash script:
chmod a+x deploy.sh
Scheduling
Now that we have our script to execute the redeployment and restart of tomcat, we'll need to schedule a one-time job using linux's 'at' command. As an example, if you want to schedule your redeployment to occur at 9pm tonight, you could use the following command:at 21:00
This will start a command prompt, where you can now specify what commands or scripts to be executed:
at> /root/deploy.sh TaskRequest /home/philip/TaskRequest.war
CTRL-D
CRTL-D will end the promptAnd that's pretty much it. If you want to view the list scheduled jobs you can use the 'atq' command:
[root@apntest1 webapps]# atq
2 2015-10-28 09:30 a root
To view the contents of the scheduled job use 'at -c id
[root@apntest1 webapps]# at -c 2
#!/bin/sh
# atrun uid=0 gid=0
# mail philip 0
umask 22
HOSTNAME=apntest1; export HOSTNAME
SHELL=/bin/bash; export SHELL
OLDPWD=/usr/local/apache-tomcat-7.0.55; export OLDPWD
USER=root; export USER
LS_COLORS=no=00:fi=00:di=00\;34:ln=00\;36:pi=40\;33:so=00\;35:bd=40\;33\;01:cd=40\;33\;01:or=01\;05\;37\;41:mi=01\;05\;37\;41:ex=00\;32:\*.cmd=00\;32:\*.exe=00\;32:\*.com=00\;32:\*.btm=00\;32:\*.bat=00\;32:\*.sh=00\;32:\*.csh=00\;32:\*.tar=00\;31:\*.tgz=00\;31:\*.arj=00\;31:\*.taz=00\;31:\*.lzh=00\;31:\*.zip=00\;31:\*.z=00\;31:\*.Z=00\;31:\*.gz=00\;31:\*.bz2=00\;31:\*.bz=00\;31:\*.tz=00\;31:\*.rpm=00\;31:\*.cpio=00\;31:\*.jpg=00\;35:\*.gif=00\;35:\*.bmp=00\;35:\*.xbm=00\;35:\*.xpm=00\;35:\*.png=00\;35:\*.tif=00\;35:; export LS_COLORS
SUDO_USER=philip; export SUDO_USER
SUDO_UID=501; export SUDO_UID
USERNAME=root; export USERNAME
PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/philip/bin; export PATH
MAIL=/var/spool/mail/philip; export MAIL
PWD=/usr/local/apache-tomcat-7.0.55/webapps; export PWD
LANG=en_AU; export LANG
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass; export SSH_ASKPASS
SHLVL=1; export SHLVL
SUDO_COMMAND=/bin/su; export SUDO_COMMAND
HOME=/root; export HOME
LOGNAME=root; export LOGNAME
CVS_RSH=ssh; export CVS_RSH
LESSOPEN=\|/usr/bin/lesspipe.sh\ %s; export LESSOPEN
SUDO_GID=501; export SUDO_GID
G_BROKEN_FILENAMES=1; export G_BROKEN_FILENAMES
cd /usr/local/apache\-tomcat\-7\.0\.55/webapps || {
echo 'Execution directory inaccessible' >&2
exit 1
}
${SHELL:-/bin/sh} << `(dd if=/dev/urandom count=200 bs=1 2>/dev/null|LC_ALL=C tr -d -c '[:alnum:]')`
/root/deploy.sh TaskRequest /home/philip/TaskRequest.war
Confirmation email
Let's take it one step further. If we want to receive email notifications of the automated deployment, we can pipe the output of the script into the mail command as follows:at 21:00
at>
/root/deploy.sh TaskRequest /home/philip/TaskRequest.war | mail -s "Webapp deployment" jo.blo@gmail.com
CTRL-D
One liner
If you want to execute the command all in one line without a command prompt, here's an exampleecho "/root/deploy.sh TaskRequest /home/philip/TaskRequest.war | mail -s \"Task request redeployed\" jo.blow@gmail.com" | at 19:45
Configuring RHEL to send emails
To install use the followingyum install postfix
If the mail command doesn't work then try installing mailx as well:
bash: mail: command not found# yum install mailx
If you're not receiving emails, it's probably because you haven't configured it yet. If you're like me using Red Hat Linux, then here are some basic instructions on how I set it up. Edit the file /etc/postfix/main.cf and set the parameter called relayhost to your smtp server:
relayhost=some.ip.address
Then restart postfix: /etc/init.d/postfix restart
Try testing by sending a test email:
echo "please work" | mail -s "Test email" email@gmail.com
If you didn't receive an email you can debug it by adding the -v flag for verbose output as follows
echo "please work" | mail -v -s "Test email" email@gmail.com
Mail Delivery Status Report will be mailed to root.
You will get the following response: Mail Delivery Status Report will be mailed to root
[root@apn-lsrv01 ~]# mail
Heirloom Mail version 12.4 7/29/08. Type ? for help.
"/var/spool/mail/root": 13 messages 2 new 11 unread
10 Mail Delivery System Thu Oct 29 08:09 68/2348 "Mail Delivery Status Report"
11 Mail Delivery System Thu Oct 29 08:13 66/2276 "Mail Delivery Status Report"
>N 12 Mail Delivery System Thu Oct 29 08:28 65/2239 "Mail Delivery Status Report"
N 13 Mail Delivery System Thu Oct 29 08:28 65/2239 "Mail Delivery Status Report"
A command prompt will appear asking you which message to open. Enter the ID of the message in this case '13' to see what went wrong with your email.
& 13
Message 13:
From MAILER-DAEMON Thu Oct 29 08:09:19 2015
Return-Path: <>
X-Original-To: root@blah
Delivered-To: root@blah
Date: Thu, 29 Oct 2015 08:09:19 +1100 (AEDT)
From: MAILER-DAEMON@blah (Mail Delivery System)
Subject: Mail Delivery Status Report
To: root@blah
Auto-Submitted: auto-replied
Content-Type: multipart/report; report-type=delivery-status;
boundary="745D91181D8A.1446066559/blah"
Status: R
Part 1:
Content-Description: Notification
Content-Type: text/plain; charset=us-ascii
This is the mail system at host blah.
Enclosed is the mail delivery report that you requested.
The mail system
<someones@email>: delivery temporarily suspended: Host or domain name not
found. Name service error for name=bad.smtp.server type=AAAA: Host not
found
In this message I realized, that the relayhost I configured earlier was incorrect. Once I obtained the correct IP address, sending emails started to work.
Use CTRL-D to end the prompt.
Happy to get some feedback on how you might have improved your bash script! Cheers!
References:
Getting the tomcat process PIDHow to use the 'at' command
Send emails from linux