How to launch your Java™ RMI server and keep it running on Unix.

Duke on Java ServerI want to open this blog by discussing a few techniques of launching a java server and it’s side kick rmi-registry. It is often that we (java developers) are faced with a requirement for launching a server and creating a failsafe mechanism. To keep it short I will focus on the Unix based platforms. If there is strong interest I will write an article on how to achieve the same thing on windows.


Before I get into details, I want to make it clear what it is that we trying to achieve here. Our goal is to launch a java program that acts as a server of some capacity. To be more specific, let’s assume that we are launching an RMI based server. In other words, we want to launch a java server that will run in the background waiting for requests. Since we are running an RMI based server, we need to launch an rmiregistry along with it. For those not familiar, rmiregistry is a separate executable usually provided along with a JDK.

Option 1. Launch a server with “&” at the end of the command string.

java myServer &

This actually would not work! When launched this way the process runs in the background but is still associated with the tty (terminal) that launched it. This means that when you exit a terminal by logging off, the terminal will send a signal to stop the jvm running your program. Needless to say there is no failsafe mechanism here.

Option 2. Use a “nohup” command.

nohup java myServer &

Nohup command is a unix command that runs a process and suspends a signal used by the terminal to stop all of the programs associated with it. This allows the program to run even after a user logged off. What happens if the jvm or the rmiregistry crashes? Once the process is kicked off using a nohup command and you log off the system, there is nothing you can do if the process decides to retire other than logging back in and manually restarting the process.

Man page for nohup.

Option 3. Use a “cron job” to test if the process is running, if not restart it.

Cron is a process dedicated to scheduling jobs. Cron can be configured to run a process every 5 minutes or so. This process will check if the server is running by trying to connect to it. If it is not running cron restarts it. The syntax is relatively simple. However, this does require that you implement a whole separate program or a complicated shell script that will check the server status and restart it if necessary. I will not get into a cron usage here and will instead jump ahead to the next solution which I believe is a bit more elegant.

Man page for cron.

Option 4. Use an “init daemon” to start a java server and an rmi-registry.

The Init daemon is an OS built-in process perfectly suited to launch any server application, including a java server and an RMI registry. There are three basic features that the init daemon offers:

  1. The init daemon will run your process in the background.
  2. The init daemon will restart your server if the server was restarted.
  3. The init daemon will monitor your process and re-spawn it if it crashed.
  4. Init daemon is very easy to configure.

Unfortunately init is often overlooked by many java developers not familiar with unix technologies.
Note: The example below was tested on Sun Solaris. Other unix based OSs have similar technology in place, however the syntax may vary.

The init daemon is configured using an /etc/inittab file. Before we configure the init daemon, we need to create 4 launch scripts, two for the server and two for the rmi-registry. Why two scripts? Because whenever the process is launched by the init daemon it runs in the super user mode. Running in a super user mode is highly undesirable and is often prohibited by the administrator. For that purpose, we have two scripts, first will switch users and second will actually launch your server. Don’t worry; these scripts are one line each!

  1. Switch users script for the rmi-registry (/usr/bin/su_for_rmiregistry):
    #!/bin/sh
    exec su –s pupsik –c “exec /home/pupsik
    /runRMI”

  1. Switch users script for the java server. (/usr/bin/su_for_javaserver)
    #!/bin/sh
    exec su –s pupsik –c “exec /home/pupsik/serverLaunchScript”
  2. Launch an RMI registry. (/home/pupsik/runRMI).
    #!/bin/sh
    exec <jre_path>/bin/rmiregistry

  3. Launch a java server. (/home/pupsik/serverLaunchScript).
    #!/bin/sh
    exec <jre_path>/bin/java –cp <classpath> myServer.jar <server class>

We used two unix commands above: SU (switch user) that switched execution from a default super user to pupsik; Exec that launched a command specified in the argument but did not create a new process and so that process id stays the same. The text, heap and stack are replaced by the new program.
Man page for su. Man page for exec.


It is time to configure the init daemon. You will need super user access to edit /etc/inittab that configures the init daemon. Add two lines used to launch scripts 1 and 2 as follows:

mm:234:respawn:/usr/bin/su_for_rmiregistry
mc:234:respawn:/usr/bin/su_for_javaserver

This tells the init daemon to launch this process during system run levels 2, 3 and 4. Respawn these processes if they crash. Now tell the init daemon to reload the inittab file by typing init –q. Check to see if your process is running using a ps command as follows:

ps –ef | grep pupsik.

For the ultimate test, use a kill command to terminate your java process. Do the PS command again, the process should be respawned automatically by the init daemon. (Make sure a new process has a different process id than the one you just killed.)

I’m sure you have questions. Let me know.

Man page for the init.

—————————————–

I thought I should add this comment to the article:

Armin that’s a good point. You are right, that if the RMI registry crashes, the java servers need to be reset.

This can be acomplished by launching the rmi registry and the java server(s) in one script.

1. The idea is that the rmi sever will be launched first.
2. The java rmi server will be launched next.
3. The launch script will than block using a wait command to check if rmi registry terminates.
4. If wait unblocks, that means that rmi registry terminated. When this happens, kill the java server(s) and repeat steps 1-3.

Below is a sample script. You can tested it by killing the rmi registry and see it respawn both rmi registry and a java server.

Here is a sample: (Note: this should work but has not been tested for syntax)

#!/bin/sh

#kick off the rmi registry
./rmiRegistry &

#store the PID of the RMI registry
rmiRegistryPID=$!
echo Started RMI registry with PID= $rmiRegistryPID”

#kick off the java server in a script
./startJavaServer &

#store PID for java server
javaServerPID=$!
echo Started Java server with PID= $javaServerPID”

While [ 1 ]
do

wait $rmiRegistryPID
echo “RMI Registry (PID=$rmiRegistryPID ) terminated…”
#kill -9 $javaServerPID
kill -TERM $javaServerPID

echo “Terminated Java Server”

./rmiRegistry &
rmiRegistryPID=$!
echo “Respawned RMI registry with PID= $rmiRegistryPID”

./startJavaServer &
javaServerPID=$!
echo “Respawned Java server with PID= $javaServerPID”

done

———————————————

startJavaServer script could look something like that:

#!/bin/sh
done=0
while [ “$done” -eq 0 ]
do

java &
jvmPID=$!
trap “kill -TERM $jvmPID;done=1? TERM
wait $jvmPID
echo “respawning JVM”

done
kill -TERM $jvmPID


8 Responses to “How to launch your Java™ RMI server and keep it running on Unix.”

  1. tolik Says:

    This perl script can be started with “nohup” command. In this example instead of using “sleep 3″ and “sleep 6″ you can put whatever processes you want (and as many as you want, just keep increasing the list. when process dies, it gets imedeatly restarted.
    NOTE: you can take out print statment, its only for demonstration.

    ————————————
    #!/bin/perl

    @cmds=(”sleep 3″, “sleep 6″);

    use threads;
    sub restart_pid {
    my ($pname)=@_;
    do { my $pid=`$pname &`; print “$pname restarted,time=”.time.”\n”; }
    while waitpid($pid, 0);
    }

    foreach $i (@cmds) { threads->create(\&restart_pid, $i); };
    sleep;
    —————————–

  2. javajiggle Says:

    This is very good solution. However, this will not restart a Java process if a server power cycled.

  3. armin Kupczok Says:

    We also need to keep rmiregistry and rmiserver running. I think option 4 works well. But there is one point which I dont know how to solve it. If either RMIServer or RMIRegistry crashes both of them must be restarted. So if only RMIServer crashes, RMIRegistry must be restarted and then RMIServer must be started (rebinding). Is there a solution for that problem

  4. armin Kupczok Says:

    The scenario above must be inverted. The problem occurs if RMIRegistry crashes. Then RMIServer must restart in order to rebind its stubs after RMIRegistry restart.

  5. celpjefscycle Says:

    Thanks for information.
    many interesting things
    Celpjefscylc

  6. JavaJiggler Says:

    Armin that’s a good point. You are right, that if the RMI registry crashes, the java servers need to be reset.

    This can be acomplished by launching the rmi registry and the java server(s) in one script.

    1. The idea is that the rmi sever will be launched first.
    2. The java rmi server will be launched next.
    3. The launch script will than block using a wait command to check if rmi registry terminates.
    4. If wait unblocks, that means that rmi registry terminated. When this happens, kill the java server(s) and repeat steps 1-3.

    Below is a sample script. You can tested it by killing the rmi registry and see it respawn both rmi registry and a java server.

    Here is a sample: (Note: this should work but has not been tested for syntax)

    #!/bin/sh

    #kick off the rmi registry
    ./rmiRegistry &

    #store the PID of the RMI registry
    rmiRegistryPID=$!
    echo Started RMI registry with PID= $rmiRegistryPID”

    #kick off the java server in a script
    ./startJavaServer &

    #store PID for java server
    javaServerPID=$!
    echo Started Java server with PID= $javaServerPID”

    While [ 1 ]
    do
    wait $rmiRegistryPID
    echo “RMI Registry (PID=$rmiRegistryPID ) terminated…”

    kill -9 $javaServerPID
    echo “Terminated Java Server”

    ./rmiRegistry &
    rmiRegistryPID=$!
    echo “Respawned RMI registry with PID= $rmiRegistryPID”

    ./startJavaServer &
    javaServerPID=$!
    echo “Respawned Java server with PID= $javaServerPID”
    done

  7. Josh Says:

    Maybe I am dense but what happens if the java server dies… glancing at this code looks like it would just stay dead.

  8. Javajiggler Says:

    Josh,
    You are right. The above script demonstrates how to restart the java server in case rmiregistry has crashed. It will not do anything in case the java server crashed.
    We will need a separate script “startJavaServer” to respawn the java server. Something like this should do the trick:

    #!/bin/sh
    done=0
    while [ “$done” -eq 0 ]
    do
    java &
    jvmPID=$!
    trap “kill -TERM $jvmPID;done=1″ TERM
    wait $jvmPID
    echo “respawning JVM”
    done
    kill -TERM $jvmPID
    echo “Out of the loop!!”

    Note, we will need to change “kill -9 $javaServerPID” to “kill -TERM $javaServerPID” in the previous script.
    I hope that helps.
    Java Jiggler

Leave a Reply