Search code examples
javabashforkprocessbuilder

Double fork from shell to run java process / jar


I have a Java application that needs to spawn another Java application. This second java application is long lived and might outlive the original java application. It's basically a big while loop that executes some networking code, and is not intended to terminate unless a specific condition happens. To launch this application, I use a bash script to double fork it, so that the original java application doesn't wait for it to complete:

How the original java app launches the shell script:

ProcessBuilder processBuilder = new ProcessBuilder(
    "myshellscript",
    "-a", "somearg",
    "-b", "anotherarg");

final Process process = processBuilder.start();
process.waitFor();
if (process.exitValue() != 0)
{
  // do something
}

The contents of the shell script:

fork() {
   echo "Going to fork" >> /tmp/output.log
   (setsid java -jar ./anotherapplication.jar "$@" &);
   echo "Exited" >> /tmp/output.log
}
fork "$@"

In "output.log", I see "Going to fork" and "Exited" messages, but I never see any logs from the "anotherapplication.jar" app, which makes me think it doesn't start successfully. It also doesn't show in the output of ps aux either, so it definitely isn't running. Is this the right way to start the second application, or am I not starting it correctly?


Solution

  • Setsid should do what you want. I can't tell why your application doesn't start, but the application will not print anything to the /tmp/output.log, simply because you don't redirect output of the setsid line to the log file. I would redirect the stdout and stderr of that line to the output.log using:

    (setsid java -jar ./anotherapplication.jar "$@" &) >>/tmp/output.log 2&>1
    

    This will almost certainly show an error documenting why it fails to start. It's often a good idea to reset the standard input and output of daemon-like processes like this anyway.