Running system commands in Java applications

UPDATE: This article has been replaced by my newer "Java exec with ProcessBuilder and Process" article. While the Java code shown in this tutorial works on simple "Java exec" cases, the new article shows how to properly read the output streams from your system command in Java threads, and also how to write to your command's standard input, if necessary.

Feel free to read this article for background/legacy information, but I strongly recommend that you use the source code I'm sharing in my newer "Java exec" article, because it resolves the standard input, output, and error problems that I didn't handle properly in the code below.

Introduction

I've read a lot about Java but one of the things I rarely see discussed is how you should go about running external system commands. Of course, you probably don't read much about this because it takes away from the portability of Java applications. For instance, if you write a Java application on a Unix system, you might be interested in running the "ps -ef" command, and reading the output of the command. For Unix systems this is great, but unfortunately, this same program won't work on a Windows system because the ps command isn't available on Windows.

Well, we're going to forget about portability for this article, and demonstrate a method that can be used to run system commands. We've received a lot of requests about this topic, so here goes.

Discussion (Runtime exec and Process)

Executing a system command is relatively simple - once you've seen it done the first time. It involves the use of two Java classes, the Runtime class and the Process class. Basically, you use the exec method of the Runtime class to run the command as a separate process. Invoking the exec method returns a Process object for managing the subprocess. Then you use the getInputStream() and getErrorStream() methods of the Process object to read the normal output of the command, and the error output of the command. What you do with the output of the command executed is entirely up to you and the application you're creating.

(Note: There is also a getOutputStream() method that you can use to write to the process, but we won't cover that method in this article. We'll cover that and a few other advanced features in a future article.)

A Java exec example

The code shown in Listing 1 provides a working example of our "Java exec" technique in a file named JavaRunCommand.java.

import java.io.*;

public class JavaRunCommand {

    public static void main(String args[]) {

        String s = null;

        try {
            
	    // run the Unix "ps -ef" command
            // using the Runtime exec method:
            Process p = Runtime.getRuntime().exec("ps -ef");
            
            BufferedReader stdInput = new BufferedReader(new 
                 InputStreamReader(p.getInputStream()));

            BufferedReader stdError = new BufferedReader(new 
                 InputStreamReader(p.getErrorStream()));

            // read the output from the command
            System.out.println("Here is the standard output of the command:\n");
            while ((s = stdInput.readLine()) != null) {
                System.out.println(s);
            }
            
            // read any errors from the attempted command
            System.out.println("Here is the standard error of the command (if any):\n");
            while ((s = stdError.readLine()) != null) {
                System.out.println(s);
            }
            
            System.exit(0);
        }
        catch (IOException e) {
            System.out.println("exception happened - here's what I know: ");
            e.printStackTrace();
            System.exit(-1);
        }
    }
}

Listing 1 (above): The file JavaRunCommand.java shows how you can run an external system command from within a Java program.

How our Java exec code works

The first thing you do is specify the command you want to run by supplying this command to the Runtime class. Because you can't create your own instance of the Runtime class, you first use the getRuntime method to access the current runtime environment and then invoke the Runtime exec method. This returns a Process object.

Everything else you do involves methods of the Process object. In this case, because we're running the "ps -ef" command on a Unix system, we just need to read the output of the command. Reading the standard error probably isn't required in this case, but I thought at the very least it was at least worth showing, if not good programming practice.

I convert the input streams with the InputStreamReader and BufferedReader so I can use the readLine() method of the BufferedReader class. Because I use these classes, this application will not compile properly with an older JDK 1.0.x compiler (these classes weren't available in 1.0.x).

Download the "Java exec" example source code

I could go on at length about this topic, but the best thing I can recommend is that you download the source code and work with it for a while. Try running different commands to see if you can get them to work properly, and try to run a command that requires input (this will be a bit more complicated).

To download the JavaRunCommand.java source code shown in Listing 1, click here. Once the file is displayed in your browser you can select the File | Save As ... option of your browser to save the code to your local filesystem.