Search code examples
javapythonshelltail

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


Solution

  • 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.