40

I need to run a command at terminal in Fedora 16 from a JAVA program. I tried using

Runtime.getRuntime().exec("xterm"); 

but this just opens the terminal, i am unable to execute any command.

I also tried this:

OutputStream out = null;
Process proc = new ProcessBuilder("xterm").start();
out = proc.getOutputStream();  
out.write("any command".getBytes());  
out.flush(); 

but still i can only open the terminal, but can't run the command. Any ideas as to how to do it?

phoenix
  • 795
  • 1
  • 7
  • 14
  • 1
    Have you tried `Runtime.getRuntime().exec(); ` You dont need to open `xterm` that is what is opening your terminal. – Karthik T Mar 12 '13 at 08:29
  • You should try `sh -s`, and you can use the code you wrote, the shell will accept the commands from the stream, or `sh -c `, and the command specified in the argument will be run. – ppeterka Mar 12 '13 at 08:30

6 Answers6

54

You need to run it using bash executable like this:

Runtime.getRuntime().exec("/bin/bash -c your_command");

Update: As suggested by xav, it is advisable to use ProcessBuilder instead:

String[] args = new String[] {"/bin/bash", "-c", "your_command", "with", "args"};
Process proc = new ProcessBuilder(args).start();
Community
  • 1
  • 1
Rahul
  • 44,383
  • 11
  • 84
  • 103
  • 6
    Usage of `Runtime.exec()` is now discouraged: use shall use ProcessBuilder instead (http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exec%28java.lang.String[],%20java.lang.String[],%20java.io.File%29) – xav Oct 16 '15 at 13:38
22

I vote for Karthik T's answer. you don't need to open a terminal to run commands.

For example,

// file: RunShellCommandFromJava.java
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class RunShellCommandFromJava {

    public static void main(String[] args) {

        String command = "ping -c 3 www.google.com";

        Process proc = Runtime.getRuntime().exec(command);

        // Read the output

        BufferedReader reader =  
              new BufferedReader(new InputStreamReader(proc.getInputStream()));

        String line = "";
        while((line = reader.readLine()) != null) {
            System.out.print(line + "\n");
        }

        proc.waitFor();   

    }
} 

The output:

$ javac RunShellCommandFromJava.java
$ java RunShellCommandFromJava
PING http://google.com (123.125.81.12): 56 data bytes
64 bytes from 123.125.81.12: icmp_seq=0 ttl=59 time=108.771 ms
64 bytes from 123.125.81.12: icmp_seq=1 ttl=59 time=119.601 ms
64 bytes from 123.125.81.12: icmp_seq=2 ttl=59 time=11.004 ms

--- http://google.com ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 11.004/79.792/119.601/48.841 ms
pradosh nair
  • 913
  • 1
  • 16
  • 28
shyan1
  • 1,003
  • 15
  • 17
  • but if the result of command execution is lengthy log then this readLine thing doesnt work at all , how to read it too? – Yash Agrawal Mar 17 '17 at 17:09
  • @YashAgrawal Can you provide the command(or similar one) that generate lengthy log, so I can test this program again ? – shyan1 Mar 17 '17 at 23:32
  • i cannot post it here because its a very length log while running hadoop commands for ex: /hadoop.../bin/hdfs jar some.jar /input /output – Yash Agrawal Mar 18 '17 at 07:14
  • @YashAgrawal I just happened to come across that there's also a question http://stackoverflow.com/questions/5711084/java-runtime-getruntime-getting-output-from-executing-a-command-line-program#answer-5711150 that handles basically the same situation. I thought you might want to check it as well, can you take a look at it to see if it helps ? – shyan1 Mar 18 '17 at 13:40
11

You don't actually need to run a command from an xterm session, you can run it directly:

String[] arguments = new String[] {"/path/to/executable", "arg0", "arg1", "etc"};
Process proc = new ProcessBuilder(arguments).start();

If the process responds interactively to the input stream, and you want to inject values, then do what you did before:

OutputStream out = proc.getOutputStream();  
out.write("command\n");  
out.flush();

Don't forget the '\n' at the end though as most apps will use it to identify the end of a single command's input.

Chris Cooper
  • 4,982
  • 1
  • 17
  • 27
7

As others said, you may run your external program without xterm. However, if you want to run it in a terminal window, e.g. to let the user interact with it, xterm allows you to specify the program to run as parameter.

xterm -e any command

In Java code this becomes:

String[] command = { "xterm", "-e", "my", "command", "with", "parameters" };
Runtime.getRuntime().exec(command);

Or, using ProcessBuilder:

String[] command = { "xterm", "-e", "my", "command", "with", "parameters" };
Process proc = new ProcessBuilder(command).start();
user1252434
  • 2,083
  • 1
  • 15
  • 21
  • Usage of `Runtime.exec()` is now discouraged: use shall use ProcessBuilder instead (http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exec%28java.lang.String[],%20java.lang.String[],%20java.io.File%29) – xav Oct 16 '15 at 13:40
  • Edited ProcessBuilder variant in. The comment in the documentation refers to ProcessBuilder being preferred to start processes with "modified environment", though, which is not used in this case. Anyway, main addition by my answer is the inclusion of how to run the command in xterm. – user1252434 Oct 16 '15 at 13:53
  • I appreciate your answer. I needed to run a makefile from Java. When I ran the command `make` it returned `TERM environment variable not set.`. But when I ran the command `xterm -e make` it worked like a charm. – Ido Jan 27 '22 at 13:42
4

I don't know why, but for some reason, the "/bin/bash" version didn't work for me. Instead, the simpler version worked, following the example given here at Oracle Docs.

String[] args = new String[] {"ping", "www.google.com"};
Process proc = new ProcessBuilder(args).start();
Akash Agarwal
  • 2,326
  • 1
  • 27
  • 57
3

I know this question is quite old, but here's a library that encapsulates the ProcessBuilder api.

mhashim6
  • 527
  • 6
  • 19