Tony Lâmpada
Tony Lâmpada

Reputation: 5459

Automatically stop "tail -f catalina.out" when exception found or server is running

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? :-)

Upvotes: 2

Views: 2589

Answers (3)

Tony Lâmpada
Tony Lâmpada

Reputation: 5459

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.

Upvotes: 0

Perception
Perception

Reputation: 80633

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.

Upvotes: 0

tripleee
tripleee

Reputation: 189749

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

Upvotes: 0

Related Questions