devDude
devDude

Reputation: 17

Run multiple system commands

I have been playing with java processes for a while and am stuck. What i want to do is run multiple system commands at the same time and print their output to console.

For example, ls -l ; cat someFile ; quit ; grep foo someOtherFile should all be running at the same time. I have read somewhere that the output of these commands should be intermixed. In addition, if there's a quit command anywhere in the string, continue executing other commands and then exit.

Right now, they are executing sequentially. How do I run them concurrently and print their output as it arrive.

String st = "ls -l ; cat someFile ; quit ; grep foo someOtherFile";

String[] rows = st.split(";");

String[][] strArray = new String[rows.length][];
int index = 0;
for(int i = 0; i < rows.length; i++) {
    rows[index] = rows[index].trim();
    strArray[index] = rows[index].split(" ");
    index++;
}
for(int i = 0; i < strArray.length; i++) {
    if(rows[i].equalsIgnoreCase("quit")) {
        System.out.println("Abort");
        break;
    }
    if(rows[i].equals("")) {
        continue;
    }
    ProcessBuilder pb = new ProcessBuilder(strArray[i]);
    pb.redirectErrorStream(true);
    Process process = pb.start();

    InputStream is = process.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);

    String line;
    while ( (line = br.readLine()) != null) {
        System.out.println(line);
    }
    br.close();
}

Upvotes: 2

Views: 245

Answers (3)

Adilson Cabral
Adilson Cabral

Reputation: 628

You should look to some documentation about concurrency, threads an such http://docs.oracle.com/javase/tutorial/essential/concurrency/.

Here an edit to your code that may work, not tested.

    String st = "ls -l ; cat someFile ; quit ; grep foo someOtherFile";

    String[] rows = st.split(";");

    String[][] strArray = new String[rows.length][];
    int index = 0;
    for(int i = 0; i < rows.length; i++) {
        rows[index] = rows[index].trim();
        strArray[index] = rows[index].split(" ");
        index++;
    }

    List<Thread> threads = new ArrayList<Thread>();

    for(int i = 0; i < strArray.length; i++) {
        if(rows[i].equalsIgnoreCase("quit")) {
            System.out.println("Abort");
            break;
        }
        if(rows[i].equals("")) {
            continue;
        }

        final int iForThread = i;

        Thread thread = new Thread() {

            public void run(){
                try{
                    ProcessBuilder pb = new ProcessBuilder(strArray[iForThread]);
                    pb.redirectErrorStream(true);
                    Process process = pb.start();

                    InputStream is = process.getInputStream();
                    InputStreamReader isr = new InputStreamReader(is);
                    BufferedReader br = new BufferedReader(isr);

                    String line;
                    while ( (line = br.readLine()) != null) {
                        System.out.println(line);
                    }
                    br.close();
                }catch(IOException e){
                    //Log some awesome error
                    //Clean up
                    //Do whatever
                }
            }
        };

        threads.add(thread);

    }

    final CyclicBarrier gate = new CyclicBarrier(threads.size() + 1); //+1 is a tip from other post

    for(Thread thread : threads){
        thread.start();
    }

    try {
        gate.await();
        System.out.println("all threads started");
    } catch (InterruptedException | BrokenBarrierException e) {
        e.printStackTrace();
        /* RONALDO OF ERROS
         * MESSI OF HANDLERS*/
    }

}

It creates an tread and executed it at the spot. I if you are just messing around I think this enough.

Edit: Added start threads at "same time"

Based on: How to start two threads at "exactly" the same time

See:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html

Upvotes: 0

darioo
darioo

Reputation: 47213

You can try code similar to this:

// command list
String st = "ls -la; cat someFile";

String[] commands = st.split(";");

for (int i = 0; i < commands.length; i++) {
    String currentCommand = commands[i].trim();

    System.out.println("Command: " + currentCommand);

    Thread thread = new Thread(() -> {
        try {
            ProcessBuilder command = new ProcessBuilder(currentCommand);
            Process process = command.start();
            InputStream is = process.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String line;

            while((line = br.readLine()) != null)    {
                System.out.println(line);
            }
            br.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    });

    thread.start();
}

Disclaimer: not tested on a Linux machine. Windows machines will probably not work. See this link regarding Windows command line process execution.

Upvotes: 0

clemep
clemep

Reputation: 124

Just put the guts of your loop inside the run() function of a new thread, and each iteration of the loop will run in a separate thread:

new Thread() {
    public void run() {
        // loop guts go here
    }
}.start();

You may have to declare a few variables as finals in order to access them inside this anonymous inner class.

Upvotes: 1

Related Questions