27

I am trying to decide as to whether to use ProcessBuilder or Commons exec,

My requirements are that I am simply trying to create a daemon process whose stdout/stdin/stderr I do not care about. In addition I want to execute a kill to destroy this process when the time comes.

I am using Java on Linux.

I know that both have their pains and pitfalls (such as being sure to use separate thread to swallow streams can lead to blocking or deadlocks, and closing the streams so not to leave open files hanging around) and wanted to know if anyone had suggestions one way or the other as well as any good resources to follow.

Lii
  • 11,553
  • 8
  • 64
  • 88
Traker
  • 2,147
  • 3
  • 23
  • 38

6 Answers6

15

The ZT Process Executor library is an alternative to Apache Commons Exec. It has functionality to run commands, capture their output, set timeouts, verify program exit status etc.

I have used it a little and I find it well-designed reasonably well-documented.

Example from the documentation

Executing a command, pumping the stderr to a logger, returning the output as UTF8 string.

 String output = new ProcessExecutor().command("java", "-version")
    .redirectError(Slf4jStream.of(getClass()).asInfo())
    .readOutput(true).execute()
    .outputUTF8();

Its documentation lists the following advantages over Commons Exec:

  • Improved handling of streams
  • Reading/writing to streams
  • Redirecting stderr to stdout
  • Improved handling of timeouts
  • Improved checking of exit codes
  • Improved API
  • One liners for quite complex usecases
  • One liners to get process output into a String
  • Access to the Process object available
  • Support for async processes ( Future )
  • Improved logging with SLF4J API
  • Support for multiple processes
Lii
  • 11,553
  • 8
  • 64
  • 88
10

commons-exec is not the best library I've ever used but it does solve the biggest pitfall in Java process invocation which is handling/consuming stdout/sterr properly. I've used ProcessBuilder in the past, which is fine, and commons-exec now which is also fine and handles most of the common cases easily.

Mike Q
  • 22,839
  • 20
  • 87
  • 129
4

May be my Exec library could be of any interest to you?

Lii
  • 11,553
  • 8
  • 64
  • 88
vorburger
  • 3,439
  • 32
  • 38
1

If you want to use a daemon process, maybe Apache Commons Daemon would be more appropriate?

malaverdiere
  • 1,527
  • 4
  • 19
  • 36
1

Commons Daemon does the job of starting a Java process as a daemon, but it doesn't do it the way one would expect. For example, when a standard C program starts a daemon (take apache or sshd for example), they perform some config sanity checks and other things (like locking a lockfile) before forking into the background. Apache Commons Daemon is a c program that launches a java app and doesn't let you put the sanity checks in the Java code AFAIK and thus breaks what I would consider important daemon facilities.

Thus, if you are looking to implement a daemon launcher that behaves similar to sshd, apache, etc. then I would suggest commons exec.

jeckhart
  • 571
  • 3
  • 10
0

Now days you can perform most tasks pretty easily using ProcessBuilder, and the need for libraries such as ZT Process Executor or Commons Exec is not so great any more.

This is great, because together with the ability to run Java programs without a separate compilation step (java SomeProgram.java), you can now use Java for shell scripting tasks.

The following code demonstrates how to fulfil the requirements given in the question:

var process = new ProcessBuilder()
        .redirectError(Redirect.DISCARD)
        .redirectOutput(Redirect.DISCARD)
        .start();

if (!process.waitFor(10, TimeUnit.SECONDS)) {
    process.destroyForcibly();
}

if (process.exitValue() != 0) {
    // Handle error
}

One thing that is often necessary for shell script style programs is to capture the output of an external command. This is still a bit tricky in Java, but it can be done using the snippet in this answer.

Lii
  • 11,553
  • 8
  • 64
  • 88