Simulating a PID file

      Comments Off on Simulating a PID file

In building new Docker containers, I’ve run into a few programs which don’t support PID files.   You know, those files that you typically find in /var/run that tell you what the process ID of a running daemon are?  PID files are important because process managers like systemd and Chaperone (which I’m using to build all my containers now) recognize PID files and can better manage process lifetimes.

So, what do you do with those pesky services that don’t support them?  Well, in implementing a new Docker container for (the very excellent) KeyBox program, I ran into just this situation, and solved it with a simple bash script:

 

#!/bin/bash

# Attempt to fork the service...
cd $APPS_DIR/KeyBox-jetty/jetty
java -Xms1024m -Xmx1024m -jar start.jar &

sleep 1 # Give it a short chance

if [ "$(jobs)" == "" ]; then
  wait $!
  joberror=$?
  echo "Keybox did not start. Exit code = $joberror"
  exit $joberror
fi

echo PID file /tmp/keybox.pid created with PID $!
echo $! >/tmp/keybox.pid
disown -a

So, this is what happens:

  1. The bash script forks off our app (in this case KeyBox and the Jetty web server).
  2. If no jobs are running, we assume something’s wrong.  Get the return code and report it.
  3. Otherwise, create our PID file.

It turns out that some of these Java apps are quite insidious and can fail without terminating (just as Apache keeps running even if a website doesn’t work).  So, to make things even a bit more robust, I added the following just before creating the PID file.  It looks for the string “loginSubmit_auth” which is the name of one of the form variables on the login page:

# Check to be sure the page served looks OK
while [ "$ok" != "yes" ]; do
  if [[ "$(wget -q -t 1 --no-check-certificate -O- https://localhost:8443)" =~ /.*loginSubmit_auth.*/ ]]; then
    echo "Valid login page detected -- KeyBox looks ready"
    ok="yes"
  elif [ "$ok" == "nnnnnnn" ]; then
    echo "KeyBox did not respond with valid results after 7 seconds."
    [ "$(jobs)" != "" ] && kill %1
    exit 1
  else
    sleep 1
    ok="n$ok"
  fi
done  

Things like this always feel a bit like a hack, but in lieu of revising the application, it’s better to be safe than sorry.

Of course, this script also assumes that the process manager is properly configured to respond to the presence of the PID file.  Chaperone does this with its pidfile service directive, but each process manager has it’s own way of doing this, so check the docs.

The final script ended up looking like this:

#!/bin/bash

# Attempt to fork the service...
cd $APPS_DIR/KeyBox-jetty/jetty
java -Xms1024m -Xmx1024m -jar start.jar &

sleep 1  # Give it a short chance

if [ "$(jobs)" == "" ]; then
  wait $!
  joberror=$?
  echo "Keybox did not start. Exit code = $joberror"
  exit $joberror
fi

# Check to be sure the page served looks OK
while [ "$ok" != "yes" ]; do
  if [[ "$(wget -q -t 1 --no-check-certificate -O- https://localhost:8443)" =~ /.*loginSubmit_auth.*/ ]]; then
    echo "Valid login page detected -- KeyBox looks ready"
    ok="yes"
  elif [ "$ok" == "nnnnnnn" ]; then
    echo "KeyBox did not respond with valid results after 7 seconds."
    [ "$(jobs)" != "" ] && kill %1
    exit 1
  else
    sleep 1
    ok="n$ok"
  fi
done  

echo PID file /tmp/keybox.pid created with PID $!
echo $! >/tmp/keybox.pid
disown -a

Happy coding!

Comments

comments