Hot questions for Using Ubuntu in processbuilder

Top Java Programmings / Ubuntu / processbuilder

Question:

I am trying to get execution results of command on Ubuntu with ProcessBuilder.I have tried to get the output result from the following techniques. But there is no result displayed, program waiting without output.

Executing Command:

 String[] args = new String[]{"/bin/bash", "-c", "pandoc -f html - t asciidoc input.html"};
Process process = new ProcessBuilder(args).start();

Getting Output Technique 1:

InputStream inputStream = process.getInputStream();
StringWriter stringWriter = new StringWriter();
IOUtils.copy(inputStream, stringWriter, "UTF-8");
// Waiting
String asciidocoutput = writer.toString();

Getting Output Technique 2:

BufferedReader reader= new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
// Waiting
 builder.append(line);
builder.append(System.getProperty("line.separator"));
}
String result = builder.toString();

Answer:

ProcessBuilder's constructor takes in a command and each subsequent String is treated as argument for the first String, recognized as the main command.

Try replacing /bin/bash with pandoc, and see if it works.

On my side, I was able to run an arbitrary command without the help of ProcessBuilder, using Runtime.getRuntime().exec(...) instead, like this:

public static void main(String[] args) throws Exception {
    Process proc = Runtime.getRuntime().exec("cmd /c ipconfig");

    BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
    String line = null;
    while((line = reader.readLine()) != null){
        System.out.println(line);
    }
}

Obtaining the expected output:

Configurazione IP di Windows


Scheda Ethernet Ethernet:

   Suffisso DNS specifico per connessione: 
   Indirizzo IPv6 locale rispetto al collegamento . : fe80::fcba:735a:5941:5cdc%11
   Indirizzo IPv4. . . . . . . . . . . . : 192.168.0.116
   Subnet mask . . . . . . . . . . . . . : 255.255.255.0
   Gateway predefinito . . . . . . . . . : 192.168.0.1

Process finished with exit code 0

If you really need to use ProcessBuilder, the same behaviour can be achieved by defining your Process this way:

Process proc = new ProcessBuilder("ipconfig").start();

simply calling the command you want to run.

Question:

final String commands[] =  {"arp", "-n", "|" ,"grep", "98:5d:ad:3d:36:ef", "|", "awk '", "{print $1}", "'"};
ProcessBuilder pb = new ProcessBuilder(commands); 

I would like to retrieve the IP, given the MAC ADDRESS. When I insert this command to the terminal (ubuntu 16.04) it works. But it doesn't work when I use it in JAVA.

What am i doing wrong?

It only works when I run it like this:

final String commands[] =  {"arp", "-n"};
ProcessBuilder pb = new ProcessBuilder(commands); 

Answer:

You need to invoke "sh" and pass to that program your piped command. Try:

ProcessBuilder b = new ProcessBuilder( "/bin/sh", "-c",
               "arp -n | grep 98:5d:ad:3d:36:ef | awk '{print $1}'" );

Question:

I am trying to extract the frequency of the most frequent line in a file using the following command:

sort file.txt | uniq -c | sort -r | head -1|  xargs

I am trying to accomplish from within a Java program, using the ProcessBuilder class. Here is how I am passing to its constructor:

ProcessBuilder builder=new ProcessBuilder("/bin/sh", "-c","sort",fileName,"| uniq -c | sort -r | head -1 | xargs");

When I run the program, it just stops executing beyond this line. There are no errors, but the program just halts at this line. What is it that I might be doing wrong?

Thanks!


Answer:

Try including a filename directly into command:

ProcessBuilder builder=new ProcessBuilder("/bin/sh", "-c","sort " + fileName + " | uniq -c | sort -r | head -1 | xargs");

Question:

I'm having a challenge with sudo invoked commands using both ProcessBuilder and Runtime.exec. I am thinking that ProcessBuilder is overall the better solution but both produce the same result - they execute shell commands fine on Ubuntu, but if I try to do a sudo -i mysql command for example:

    public static void runProcess(String[] process) {
        String s = null;
        try { 
            Process p = new ProcessBuilder(process).start();
            BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
            BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            while ((s = stdInput.readLine()) != null) { System.out.println(s); }
            while ((s = stdError.readLine()) != null) { System.out.println(s); }
        } catch (IOException e) { e.printStackTrace(); }
    }   

These 2 commands work:

        String[] cmdArgs0 = { "sudo", "echo", "Done" };
        runProcess(cmdArgs0);

        String[] cmdArgs1 = { "bash", usbDrivePath+"/ASWebUI/Install.sh" };
        runProcess(cmdArgs1);

But this does not:

        String[] cmdArgs2 = { "sudo", "-i", "mysqldump", "Core", ">", cachePath+"/SQLDumps/Core.sql" };
        runProcess(cmdArgs2);

Error:

mesg: ttyname failed: Inappropriate ioctl for device
mysqldump: Couldn't find table: ">"

Answer:

ProcessBuilder doesn't allow you to redirect the output using > character. Instead you can use processBuilder.redirectOutput() method to specify the desired output.

File dumpFile = new File("Core.sql");
processBuilder.redirectOutput(Redirect.to(dumpFile));

Or even use --result-file option of mysqldump to specify the dump file:

mysqldump [options] --result-file=dump.sql

Question:

Code below prints output of executing process (using different thread for output):

public static void main(String[] args) throws InterruptedException,
        IOException {
    ProcessBuilder builder = new ProcessBuilder("some_command");
    final Process process = builder.start();
    final Thread ioThread = new Thread() {
        @Override
        public void run() {
            try {
                final BufferedReader reader = new BufferedReader(
                        new InputStreamReader(process.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println(line);
                }
                reader.close();
            } catch (final Exception e) {
                e.printStackTrace();
            }
        }
    };
    ioThread.start();
    process.waitFor();
}

So, if I run this code with

ProcessBuilder builder = new ProcessBuilder("ping","8.8.8.8");

output will be like this:

PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=57 time=205 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=57 time=202 ms
...

But if I run

ProcessBuilder builder = new ProcessBuilder("wvdial");

then command will be executed (wvdial will start) but there will be no output in BufferedReader. wvdial in terminal shows output text.

Why wvdial gives no output for ProcessBuilder?


Answer:

Maybe it writes to stderr? process.getErrorStream()

Most UNIX programs avoid writing information messages for humans to stdout. Especially batch programs. stdout is for program results, for data output, not for informational messages.

You might also be able to make sense of exit code thus abolishing the need of output parsing.

Question:

Hello and thanks in advance, I have the following problem: I have a GUI and with a button I need to launch a c++ program that is on the same machine. This program uses a particular framework called SSM (ROS like) for sharing data. The program itself works fine when started from terminal but when I start it with java process builder I cannot access to any data but I can still see the process running.

I'm using Ubuntu 14.04 and OpenJDK7. The code that I'm using is the following (Updated according to the comment):

ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectOutput(Redirect.INHERIT);
builder.redirectError(Redirect.INHERIT);    
builder.start();

where command comes from some data that I receive via UDP:

command[0] = Main_gui.getHomePath()+"PFforAEV_autoCalib_20140418/PFforAEV0.2.2";
command[1] = String.valueOf(initialPosition[0]);
command[2] = String.valueOf(initialPosition[1]);
command[3] = String.valueOf(initialPosition[2]);
command[4] = "walllandmark_F41_20130125";

To be more specific the process PFforAEV0.2.2 is there, running, but it seems that it does not use any CPU or memory. I can't access the data via the framework. Looks like if it is just hanging.

If you need more detail just ask.

Can someone help me? Thank you.


Answer:

You have to read from the InputStream of the stdout and stderr of the child process, or redirect them to the streams of the parent process:

ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectOutput(Redirect.INHERIT);
builder.redirectError(Redirect.INHERIT);
builder.start();

See this example