2

I have set up an automated deployment script (in shell script) for my web application.

It uses java, tomcat, maven and a postgres database.

The deployment script does this:

  1. builds the deployable application from source repository
  2. stops tomcat
  3. applies database migration patches
  4. deploys the war files in tomcat
  5. starts tomcat (by invoking $TOMCAT_HOME/bin/startup.sh)
  6. exits with a success message

It's all working and it's pretty neat - but it needs a little improvement. You see, even though it exits with a success message, sometimes the deploy was not successful because the web application did not start correctly.

I would like to refactor steps 5 and 6 so that after bring up the tomcat server, the deployment script would "tail -f" in the catalina.out file, looking either for a "server started successfully" message or an exception stack trace.

The tail -f output up to that point should be part of the output of the deployment script, and step 6 would "exit 0" or "exit 1" accordingly.

I know that should be possible, if not in shell script, maybe with python. The problem is I'm a java specialist - and by specialist I mean I suck at everything else :-)

Help please? :-)

Tony Lâmpada
  • 5,301
  • 6
  • 38
  • 50
  • Look at Python's [subprocess.Popen](http://docs.python.org/library/subprocess.html#subprocess.Popen) – snies May 25 '12 at 03:34
  • As far as I know you might want to `tail -f` the localhost..log, some exceptions go there instead of catalina.out. It's true for my environment, and I'm not sure why. – xiaofeng.li May 25 '12 at 03:36
  • `tail -f` basically runs an endless loop on the file, should the script just `exec` that on success or do you mean just `tail` and exit successfully? – tripleee May 25 '12 at 03:43
  • While Popen can be used to scan the output of `tail -f` it may be easier to just use python's file access functions like for example here: [tail-f-in-python](http://stackoverflow.com/questions/5326405/understanding-the-tail-f-in-python) – snies May 25 '12 at 03:53
  • Thanks snies. That solved it (http://stackoverflow.com/questions/4417962/stop-reading-process-output-in-python-without-hang) – Tony Lâmpada May 28 '12 at 21:06
  • I'll come back later to post the solution – Tony Lâmpada May 28 '12 at 21:07

3 Answers3

0

Maybe something like this?

tmp=$(mktemp -t catalina.XXXXXXX) || exit 136
trap 'rm "$tmp"' 0
trap 'exit 255' 2 15
tail -n 200 catalina.out >"$tmp"
if grep -q error "$tmp"; then
    cat "$tmp"
    exit 1
fi
exit 0

On the other hand, if startup.sh were competently coded, you could just

if startup.sh; then
    tail -f catalina.out
else
    exit $?
fi

which can be shortened to

startup.sh || exit $?
tail -f catalina.out
tripleee
  • 175,061
  • 34
  • 275
  • 318
0

As an alternative, you might want to take a look at the Apache Tomcat Manager application. It supports, amongst other things:

  • Deploying applications remotely, and from local paths
  • Listing currently deployed applications
  • Reloading existing applications
  • Starting an existing application
  • Stopping an existing application
  • Undeploying an existing application

The manager provides a web interface that can be called via curl, and which returns simple, parseable messages to indicate the status of the invoked command. Management functions can also be invoked via JMX, or Ant scripts. All in all, a very handy tool.

Perception
  • 79,279
  • 19
  • 185
  • 195
0

I ended up implementing a solution using Python's subprocess.Popen, as suggested by @snies.

Here's what it looks like:

waitForIt.py

#! /usr/bin/env python
import subprocess
import sys

def main(argv):
    filename = argv[1]
    match=argv[2]
    p = subprocess.Popen(['tail', '-n', '0', '-f', filename], stdout=subprocess.PIPE)
    while True :
        line = p.stdout.readline()
        print line ,
        if match in line :
            break
    p.terminate()

if __name__ == "__main__":
    main(sys.argv)

tailUntil.sh

#!/bin/bash
set -e

filename=$1
match=$2

thisdir=$(dirname $0)
python $thisdir/waitForIt.py "$filename" "$match"

and then

startTomcat.sh

${TOMCAT_HOME}/bin/startup.sh
logDeploy.sh "Agora vamos dar um tail no catalina.out..."
util_tailUntil.sh "$TOMCAT_HOME/logs/catalina.out" 'INFO: Server startup in '

It doesn't do what I originally intended (it still exits with return code 0 even when there is a stacktrace - but that could be changed with a little bit more of Python magic), but all of tomcat's initialization log is part of the automated deploy out (and easily viewable on Jenkins' deploy job) - so that's good enough.

Tony Lâmpada
  • 5,301
  • 6
  • 38
  • 50