Some terminal commands run via Java don't display output in Linux - java

I'm trying to write a Java program to run terminal command. Googling and SO got me to here:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Detector {
public static void main(String[] args) {
String[] cmd = {"ls", "-la"};
try {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) !=null){
System.out.println(line);
}
p.waitFor();
} catch (IOException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
So far, so good. The problem is if I try to run a command like "python -V" via
String[] cmd = {"python", "-V"};
The program will run, but no output is actually printed out. Any ideas?

The output you see on your command line when running python -V is actually being printed to standard error. To capture this, you need to use a different InputStream, such as this:
BufferedReader errorReader = new BufferedReader(
new InputStreamReader(p.getErrorStream()));
The rest of your code is fine.

Related

WMIC Java command not working after exe installation

A very simple code running in the debugging mode perfectly but not working after installation of exe, giving no response/result in return. even no errors to trace.
After building a .exe and installing on my PC its happening, very strange.
tried process builder but the same thing, anyway to check/trace it. maybe paths ?
StringBuilder b = new StringBuilder();
Process p = Runtime.getRuntime().exec("wmic diskdrive get signature");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
b.append(line);
}
Please note: CMD /c before commands also return an empty response in actual env.
An internal windows command with arguments, like "wmic diskdrive ..."
can be executed easily by wrapping it up inside a cmd window.
Here is the working code snippet for running the wmic command encapsulated in a cmd window:
import java.io.*;
public class Wmic {
public static void main(String[] args) {
StringBuilder b = new StringBuilder();
try {
// Initialize a process object to run
// wmic command and its parameters
// inside a cmd window
Process process = Runtime.getRuntime()
.exec("cmd /c C:\\Windows\\System32\\wbem\\WMIC.exe diskdrive get signature");
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
b.append(line);
}
} catch (Exception ex) {
b.append(ex.toString());
}
System.out.println("Output: \n" + b.toString());
}
}
Output:
>javac Wmic.java
>java Wmic
Output:
Signature
More information:
https://mkyong.com/java/how-to-execute-shell-command-from-java/
The ProcessBuilder constructor takes a list of strings. When using ProcessBuilder to run a command, I separate all the words in the command into separate strings.
I read the output of the process in a separate thread. And I always wait for the command, that I launched via ProcessBuilder, to terminate.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
public class PrcBldTs {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("wmic","diskdrive","get","signature");
try {
Process proc = pb.start();
StreamGobbler error = new StreamGobbler(proc.getErrorStream());
StreamGobbler output = new StreamGobbler(proc.getInputStream());
Thread stdout = new Thread(output);
Thread stderr = new Thread(error);
stdout.start();
stderr.start();
int result = proc.waitFor();
stdout.join();
stderr.join();
System.out.println("Exit status = " + result);
if (result != 0) {
System.out.println(error.getContents());
}
else {
System.out.println(output.getContents());
}
}
catch (IOException | InterruptedException x) {
x.printStackTrace();
}
}
}
class StreamGobbler implements Runnable {
private BufferedReader reader;
private StringWriter sw;
public StreamGobbler(InputStream is) {
InputStreamReader isr = new InputStreamReader(is);
reader = new BufferedReader(isr);
sw = new StringWriter();
}
public String getContents() {
return sw.toString();
}
public void run() {
try {
String line = reader.readLine();
while (line != null) {
sw.append(line);
sw.append(System.lineSeparator());
line = reader.readLine();
}
}
catch (IOException xIo) {
throw new RuntimeException(xIo);
}
}
}
Running the above code gave me the following output.
Exit status = 0
Signature
1145609371

java program using ProcessBuilder working in command prompt but not in eclipse

I am trying to execute an .jar file using java code and I have used ProcessBuilder for that. I have placed the java file and the jar file I need to execute in the same folder and tried executing my code it worked :) . But, Now I have created a project in eclipse and I have configured the build path for that jar and I tried executing the java file but I am not abel to do so :(
My java file : Test.java
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
public class Test
{
public static void main(String a[]) throws Exception
{
try
{
String url="some error url";
ProcessBuilder pb = new ProcessBuilder("java","-jar","myjarname.jar","attr 1","attr 2","attr 3");
Process p = pb.start();
System.out.println(p.getInputStream().read());
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
if(line.contains("https://"))
{
url=line.substring(line.lastIndexOf("https")+0);
System.out.println(url);
}
}
System.out.println(p.getErrorStream().read());
java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
}
catch (Exception e)
{
System.out.println(e);
}
}
}

how to know weather server has started using runtime.getruntime().exec

Hi have written code for starting the server.
The code is as given below.
package javacode;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExecuteShellComand {
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String command = "command to be executed to run the server(Path)";
String output = obj.executeCommand(command);
System.out.println(output);
}
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
}
The server has started in background when i run the java code, but i am using the linux command to check weather the server has started.
I want to know what return value is stored in Process object when i run
Process pro=Runtime.getRuntime().exec(command)
You can use process.exitValue() to retrieve the return value of the command you have executed.
Please have also a look at the javadoc: http://docs.oracle.com/javase/8/docs/api/java/lang/Process.html#exitValue--
p = Runtime.getRuntime().exec(command);
p.waitFor();
System.out.println("Command '"+command+"' finished with return code "+p.exitValue());

pipe telnet output to logfile with tee command using Java process exec

Concurrency and stream reading in a project for a simple MUD client is proving a bit of headache, so I'm trying to find an alternative. The tee command looks to fit the bill for concurrently splitting output between a file and the terminal. How do I then send messages through the telnet session?
Splitting remote output between the console and a file:
thufir#dur:~/NetBeansProjects/TelnetConsole$
thufir#dur:~/NetBeansProjects/TelnetConsole$ telnet rainmaker.wunderground.com 3000 | tee out.txt
Trying 38.102.137.140...
Connected to rainmaker.wunderground.com.
Escape character is '^]'.
------------------------------------------------------------------------------
* Welcome to THE WEATHER UNDERGROUND telnet service! *
How do I then pipe or somehow send Java messages to the system telnet client? Or, perhaps, would it make more sense to use exec and start the telnet session, and tee, from within Java? Just looking for a good approach.
Yes, exec sounds like a better solution since you want to control both input and outpud data. And do you really need tee in when you use exec, I don't understand why...
Also take a look at netcat instead of telnet - telnet has some special character handling that could give you trouble if you plan to send binary data.
By no means functioning code, but definitely simpler than using Apache TelnetClient. However, it's not possible to use the pipe command(?) with java exec:
package exec;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
class Ideone {
public static void main(String[] args) throws IOException {
new Ideone().start();
}
public void start() throws IOException {
String[] s = new String[6];
s[0] = "telnet";
s[1] = "rainmaker.wunderground.com";
s[2] = "3000";
s[3] = "|";
s[4] = "tee";
s[5] = "out.log";
for (int i=0;i<s.length;i++ ) {
System.out.println(s[i]);
}
Process process = Runtime.getRuntime().exec(s);
OutputStream stdin = process.getOutputStream();
InputStream stderr = process.getErrorStream();
InputStream stdout = process.getInputStream();
read();
write(stdout);
}
private void parseLog() {
//read the log file, automate responses
}
private void write(InputStream stdin) throws UnsupportedEncodingException, IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(stdin, "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
private void read() {
Thread read = new Thread() {
String command = null;
#Override
public void run() {
BufferedReader bufferedInput = new BufferedReader(new InputStreamReader(System.in));
do {
try {
command = bufferedInput.readLine();
} catch (IOException ex) {
System.out.println(ex);
} finally {
}
} while (true);
}
};
read.start();
}
}

Process requires redirected input

I have a UNIX native executable that requires the arguments to be fed in like this
prog.exe < foo.txt.
foo.txt has two lines:
bar
baz
I am using java.lang.ProcessBuilder to execute this command. Unfortunately, prog.exe will only work using the redirect from a file. Is there some way I can mimic this behavior in Java?
Of course,
ProcessBuilder pb = new ProcessBuilder("prog.exe", "bar", "baz");
does not work.
Thanks!
ProcessBuilder pb = new ProcessBuilder("prog.exe");
Process p = pb.start();
OutputStream pos = p.getOutputStream();
InputStream fis = new FileInputStream("file.txt");
byte[] buffer = new byte[1024];
int read = 0;
while((read = fis.read(buffer)) != -1) {
pos.write(buffer, 0, read);
}
fis.close();
Not tested, but something like this should work.
I ended up doing something like this and it works. Thanks for all the help!
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.List;
public class UserInp {
public static void main(String[] args) {
new UserInp().sample();
}
public void sample() {
String command = "foo.exe";
List<String> args = new LinkedList<String>();
args.add("bar");
args.add("baz");
ProcessBuilder pb = new ProcessBuilder(command);
java.lang.Process process = null;
try {
process = pb.start();
} catch (IOException ex) {
//--
}
OutputStream os = process.getOutputStream();
PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(os)));
final InputStream is = process.getInputStream();
new Thread(new Runnable() {
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (java.io.IOException e) {
}
}
}).start();
for (String arg : args) {
pw.println(arg);
}
pw.close();
int returnCode = -1;
try {
returnCode = process.waitFor();
} catch (InterruptedException ex) {
//--
}
System.out.println(returnCode);
}
}
The redirection is setup by the shell you need todo this manually, something like that:
Process proc = pb.start();
OutputStreamWriter os = new OutputStreamWriter(proc.getOutputStream());
// then write the data from your file to os
// ...
os.close();
Did you try to wrap prog.exe into a script which accepts arguments and deal with prog.exe ?
I assume you're using a shell, so it's quite simple to set up a bash script.
If I understand your problem, the script would look like :
#!/usr/bin/bash
echo $1 > file
echo $2 >> file
prog.exe < file
remove file
Build the process using a ProcessBuilder, then use process.getOutputStream() to get an OutputStream that will pipe to the standard input of the process.
Open the file using normal Java techniques, read the contents of the file and write it to the OutputStream going to the Process you made with the ProcessBuilder.
The problem you have right now is that you're calling the ProcessBuilder to launch
$ prog.exe foo bar
Which is probably nothing close to what you want to achieve.

Categories

Resources