0

I need to execute the following script from Java and be able to view the results on console. But the echo statements are not visible on console. After spending some time on the web I was able to understand that I need to take control of the input output streams to be able to do this. But I didn't get information that I need to make this possible.

I have posted the script and the Java statements below:

Script:

#!/bin/sh
echo "Hello World"
echo "$1 $2"
exit 0

Java Code:

List<String> command = new ArrayList<String>();
command.add("sh");
command.add("sript.sh");
command.add("Technopath007");
command.add("Dennis");
ProcessBuilder builder = new ProcessBuilder(command);
Process process = builder.start();
BufferedReader is = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = is.readLine()) != null)
    System.out.println(line);       

The existing threads on the topic doesn't seem to work.

Please do let me know what I am missing here. Thanks in advance.

Naveen Dennis
  • 1,223
  • 3
  • 24
  • 39
  • Can you show the code you are actually using, not just what it replicates? – RealSkeptic Oct 22 '14 at 15:48
  • The first two code snippets are the ones I am using.. and I have edited the question accordingly – Naveen Dennis Oct 22 '14 at 16:00
  • Could it possibly be that you are calling the wrong script or from another working directory? If that happens, you'd probably not get anything on the output stream, only on the error stream. – RealSkeptic Oct 24 '14 at 17:11

2 Answers2

0

Use a BufferedReader

Something like this:

BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
string line = "";
while ((line = reader.readLine()) != null)
    System.out.println(line);
reader.Close();
user1274820
  • 7,786
  • 3
  • 37
  • 74
  • It doesn't work. I have tried this. And did so again just now. – Naveen Dennis Oct 22 '14 at 16:15
  • I don't have a java compiler on this computer so I can't really test it for you. Try taking a look at this thread: http://stackoverflow.com/questions/3643939/java-process-with-input-output-stream – user1274820 Oct 22 '14 at 16:25
  • 1
    Make sure you put the code I posted before the line: process.waitFor(); process.waitFor() can probably just be removed. There's no point in waiting for the program to stop executing when what you really want your program to do is display the output until the new process exits. – user1274820 Oct 22 '14 at 16:26
  • Any luck? Were you able to get it working? – user1274820 Oct 22 '14 at 19:07
-1

Try this:

/** Execute a command where each parameter is in the string array. It is better to
 * do such a call this way because passing a single string to the java
 * Runtime.getRuntime().exec("single long string") method invokes StringTokenizer
 * to split the string into an array of strings and it does a poor job at it.
 *
 * I.e. The string:
 *    ksh -c "mkdir /tmp/test"
 *
 * is split thus:
 *
 *    ksh
 *    -c
 *    "mkdir
 *    /tmp/test"
 *
 * and then the shell interpreter complains about unmatched quotes.
 *
 * Returns a list which is whatever was put
 * on the stdout, followed by what was put on stderr.
 * @param exec the execution array, the first entry is the executable to run.
 * Don't forget that shell builtin command must be run within a shell.
 * @return The output list.
 */
public List executeExactCommand(String exec[])
{
    int exitCode   = 3;  // Assume we failed
    List execOutput = new ArrayList();

    String execCmd = "";
    int    i;

    for (i = 0; i < exec.length; ++i) {
        execCmd += (((i != 0) ? " " : "") + exec[i]);
    }

    try {
        Process p = Runtime.getRuntime().exec(exec);

        try {
            InputStream  is   = p.getInputStream();
            StringBuffer desc;
            int          chr = 0;

            while (chr >= 0) {
                desc = new StringBuffer(5192);
                chr  = is.read();

                for (i = 0; (i < 5192) && (chr >= 0) && (chr != '\n'); chr = is.read()) {
                    // Because of Bill Gates, everyone in the world has to
                    // process for a possible, useless, RETURN character.
                    if (chr != '\r') {
                        desc.append((char) chr);
                        ++i;
                    }
                }

                if ((chr >= 0) || (desc.length() != 0)) {
                    execOutput.add(desc.toString());
                }
            }

            is  = p.getErrorStream();
            chr = 0;

            while (chr >= 0) {
                desc = new StringBuffer(5192);
                chr  = is.read();

                for (i = 0; (i < 5192) && (chr >= 0) && (chr != '\n'); chr = is.read()) {
                    // Because of Bill Gates, everyone in the world has to
                    // process for a possible, useless, RETURN character.
                    if (chr != '\r') {
                        desc.append((char) chr);
                        ++i;
                    }
                }

                if ((chr >= 0) || (desc.length() != 0)) {
                    execOutput.add(desc.toString());
                }
            }

            exitCode = p.waitFor();

            if (withCommandTrace) {
                execOutput.add("execCmd = " + execCmd + " (" + exitCode + ")");
            }
        }
        catch (InterruptedException x) {
            System.err.println("Error command interupted, cmd='" + execCmd + "'");
            System.err.println("Caught: " + x);
            execOutput.add("Error command interupted, cmd='" + execCmd + "'");
            execOutput.add("" + exitCode);
        }
    }
    catch (IOException x) {
        // couldn't exec command
        System.err.println("Error executing command, command=" + execCmd);
        System.err.println("Caught: " + x);
        execOutput.add("Error executing command, cmd='" + execCmd + "'");
        execOutput.add("" + exitCode);
    }

    if (withCommandTrace) {
        for (i = 0; (execOutput != null) && (i < execOutput.size()); ++i) {
            System.out.println((String) execOutput.get(i));
        }
    }

    return execOutput;
}

You would call it using something like this:

List eachOutputLines = executeExactCommand(["bash", "-c", "ls -la /"]);
cpu
  • 567
  • 4
  • 6
  • There are a lot of things I don't care for in this code: (1) doesn't read from the streams in parallel threads, as is technically required to avoid blocking; (2) reads one byte at a time without buffering; (3) doesn't handle Unicode; (4) improper handling of `\r` line feeds; (5) lack of generics; (6) duplicated code. – John Kugelman Oct 23 '14 at 17:33
  • To expand on point (1), you need to drain the input and error streams simultaneously because either one could fill up its internal buffer. If that happens, the process will block. The program can write to stdout or stderr at any time, so it's not safe to read from one first and then read from the other. It's not common, but if a program were to write more than 4KB or so to stderr this code could hang. – John Kugelman Oct 23 '14 at 17:38
  • I agree, it's not great code and it could be improved greatly. It was written for executable that definitively terminate, and if they write anything to stderr, it's the last thing they write before quitting. – cpu Oct 23 '14 at 19:50