java shell

From Noah.org
Revision as of 11:36, 15 March 2010 by Root (Talk | contribs) (Created page with 'Category: Engineering This shows how to call an external script from Java. This is intended for UNIX systems, but may work under other systems if you substitute a different …')

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


This shows how to call an external script from Java. This is intended for UNIX systems, but may work under other systems if you substitute a different shell or if you install CYGWIN.

import java.io.*;
import java.util.*;

public class shell
{

    /** This tests the runBashShellCommand method.
     *  The following are some examples of how it works:
     *
     *      $ java shell echo Hello
     *      0
     *      Hello
     *
     *      $ java shell "echo Hello; exit 1"
     *      1
     *      Hello
     *
     *      $ java shell "echo Hello; exit 0"
     *      0
     *      Hello
     */

    public static void main(String args[])
        throws IOException, java.lang.InterruptedException
    {
        System.out.println (runBashShellCommand (args));
    }

    /** This runs a command in a Bash shell and returns the output.
     *
     * For example, the following should print "hello":
     *
     *      String [] args = {"foo=hello", ";", "echo", "$foo"};
     *      System.out.println (runBashShellCommand (args));
     *
     * You may combine commands and arguments into a single string.
     * This is equivalent to the previous example:
     *
     *      String [] args = {"foo=hello ; echo $foo"};
     *      System.out.println (runBashShellCommand (args));
     *
     * This method will CLOSE the stdin of the subprocess so that it cannot
     * read from this filedescriptor. For example, the following should be
     * safe; Bash will simply set 'foo' to an empty string instead of blocking
     * on the 'read' call.
     *
     *      String [] args = {"read", "foo", ";", "echo", "$foo"};
     *      System.out.println (runBashShellCommand (args));
     *
     * Comments: This method is probably overkill.
     *
     * @author Noah Spurrier
     * @param args The first element should be the command to be run.
     *               Additional elements should be arguments.
     * @return the output of the command as a String. The first line of the
     *          string will be the exit code from the command that was run.
     * @throws IOException if there was a problem with the subshell.
     * @throws InterruptedException if the subshell was killed.
     */

    public static String runBashShellCommand (String args[])
        throws IOException, java.lang.InterruptedException
    {
        java.util.List<String>
            command_and_args = new java.util.ArrayList<String> ();
        command_and_args.add ("/bin/bash");
        command_and_args.add ("-c");
        StringBuffer cmd_string = new StringBuffer ();
        for (String arg : args) { cmd_string.append (arg).append (' '); }
        command_and_args.add (cmd_string.toString().trim());

        // Start Bash and script.
        ProcessBuilder pb = new ProcessBuilder (command_and_args);
        pb.redirectErrorStream (true);
        Process process = pb.start ();

        //////////////////////////////////////////////////////////////////////
        // WARNING: There is a race condition here. We want the subprocess to
        // have its stdin cutoff BEFORE it actually tries to read from stdin.
        // This is mainly to be proper; not to prevent any sort of dead-lock.
        // There is no danger that this will block us since the subprocess runs
        // asynchronously. This shouldn't be a big deal, but it should be
        // tested to be sure. -- Noah
        process.getOutputStream().close();

        // Get output from the command.
        BufferedReader br = new BufferedReader (new
                InputStreamReader (process.getInputStream()));
        StringBuffer out = new StringBuffer ();
        String line = null;
        while ((line = br.readLine ()) != null)
        {
            out.append (line).append ('\n');
        }
        // Wait for process to finish.
        int exit_code = process.waitFor();
        out.insert (0, String.valueOf(exit_code) + "\n");
        return out.toString();
    }
}