Running command from java produces empty output - java

I need to run the below comand using java but it is running fine in terminal as
svn list http://192.168.0.19/svn/cc/Branch/Jobs/tt/jobs/ --username prasadh --password prasadh2k > output.txt
But when running the same via process builder it is returning empty result.
My code:
ProcessBuilder pb = new ProcessBuilder("cmd", "C:\\Users\\dev112\\output", "svn", "list", "http://192.168.0.19/svn/cadgraf/Branch/Jobs/T0003SATHYABAMAT/Completedjobs", "--username", "prasadh", "--password", "prasadh2k", ">", "output.txt");
pb.redirectErrorStream(true);
try {
Process p = pb.start();
new Thread(new InputConsumerforImageMagick.InputConsumer(p.getInputStream())).start();
try {
System.err.println("Exited with: " + p.getErrorStream());
} catch (Exception ex) {
Logger.getLogger(AddImage.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (IOException ex) {
Logger.getLogger(AddImage.class.getName()).log(Level.SEVERE, null, ex);
}

I/O redirection doesn't work well with ProcessBuilder. You should either call cmd.exe with
new ProcessBuilder("cmd", "/c", "svn ... > output.txt");
(i.e. you have to call cmd with exactly two arguments)
or you must redirect yourself, that is you need to start a background thread which reads stdout from the process and writes it to output.txt. In that case, you should use:
new ProcessBuilder("svn", "list", ...);
The former is brittle when you have spaces in arguments. So I suggest the latter even though the Java code is much more complex.
You should also have a look at Commons Exec which makes it much easier to deal with external processes.
Or with Java 7, you can use pb.redirectOutput();

Don't go through cmd. Just run the command directly:
final Path cwd = Paths.get("c:\\Users\\dev112\\output");
Files.createDirectories(cwd);
final Path outfile = cwd.resolve("output.txt");
final ProcessBuilder pb = new ProcessBuilder("svn", "list",
"http://192.168.0.19/svn/cadgraf/Branch/Jobs/T0003SATHYABAMAT/Completedjobs",
"--username", "prasadh", "--password", "prasadh2k");
pb.directory(cwd.toFile());
pb.redirectOutput(outfile.toFile());
final int retcode = pb.start().waitFor();
What is more, why do you get the process' standard output if you output to a file? Do one or the other, not both. If you output to a file then read the contents of that file after the command is executed.
The sample above outputs to a file; just open a stream to that file afterwards using Files.newInputStream(outfile) (well, that is, if retcode is 0; if it isn't, your command has ended with an error; which also means that you should redirect stderr somewhere, too)

This works for me:
String command = "svn list http://192.168.0.19/svn/cc/Branch/Jobs/tt/jobs/ --username prasadh --password prasadh2k";
ProcessBuilder processBuilder = new ProcessBuilder(command.split());
processBuilder.redirectOutput(new File("C:/Users/dev112/output/", "output.txt"));
processBuilder.start();

Related

Entering a series of commands in git bash through java code

Am trying to get a series of commands on git bash one after the other. I can open the terminal through the code but after that wasn't successful with entering anything. For instance this is the code I tried
String [] args = new String[] {"C:\\Program Files\\Git\\git-bash.exe"};
String something="hi how are you doing";
try {
ProcessBuilder p = new ProcessBuilder();
var proc = p.command(args).start();
var w = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
w.write(something);
} catch (IOException ioException){
System.out.println(ioException);
}
Please let know how to be able to do enter a series of commands into git bash through the code.
The problem is that the command git-bash.exe opens the terminal window but the window's input is still the keyboard, so trying to write to the OutputStream that is returned by method getOutputStream(), in class Process does nothing. Refer to this question.
As an alternative, I suggest using using ProcessBuilder to execute a series of individual git commands. When you do that, your java code gets the command output.
Here is a simple example that displays the git version.
import java.io.IOException;
public class ProcBldT4 {
public static void main(String[] args) {
// C:\Program Files\Git\git-bash.exe
// C:\Program Files\Git\cmd\git.exe
ProcessBuilder pb = new ProcessBuilder("C:\\Program Files\\Git\\cmd\\git.exe", "--version");
pb.inheritIO();
try {
Process proc = pb.start();
int exitStatus = proc.waitFor();
System.out.println(exitStatus);
}
catch (IOException | InterruptedException x) {
x.printStackTrace();
}
}
}
When you run the above code, the git version details will be written to System.out.
Also, if the git command fails, the error details are written to System.err.
You need to repeat the code above for each, individual git command that you need to issue.

Java ProcessBuilder: How to suppress output instead of redirecting it

I'm using a ProcessBuilder to execute commands and redirect the output. I now want to add the possibility to have no output at all.
Of course I could redirect into a file, but this would leave unnecessary files on the users system.
I am looking for a solution that
works on all platforms, including Windows (e.g. not redirecting to /dev/null)
does not misuse try-catch (e.g. redirecting to null and ignore the exception)
The only way I could find was this:
ProcessBuilder processBuilder = new ProcessBuilder(command);
if (suppressOutput) {
processBuilder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
}
But that prints to the underlying shell, which is not literally "no output".
Here is my use of processBuilder with output not surpressed:
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.directory(new File(workingdir));
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
while (process.isAlive()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) { }
// check for termination request
if (terminationRequest()) {
process.destroy();
return -1;
}
}
return process.exitValue();
The DISCARD redirect option has been added in Java 9. You could use that if you upgrade Java. Otherwise, you could simply replicate that behaviour because the DISCARD redirect enum uses a file instance which redirects to null device as below.
private static File NULL_FILE = new File(
(System.getProperty("os.name")
.startsWith("Windows") ? "NUL" : "/dev/null")
);
Then you could use the overloaded redirectOutput method;
if (suppressOutput) {
processBuilder.redirectOutput(NULL_FILE);
}
This is identical to Java 9's behaviour.
The Java 9+ solution for discarding the output of the Process:
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectOutput(Redirect.DISCARD);
processBuilder.redirectError(Redirect.DISCARD);
Process process = processBuilder.start();

I've already created a Process Builder. How do I run all of the programs in the Process builder?

Heere is the code I have so far. How do I have miktex-pdftex run?
List<String> processes = new ArrayList<String>();
processes.add("miktex-pdftex --output-directory=[Directory] [file_name].tex");
ProcessBuilder processbuild = new ProcessBuilder(processes);
First, you need to make sure the command you are using actually works at the command. If it does not, then it's not going to work in Java.
Next, one of the main reasons for using ProcessBuilder is to deals with spaces in the command/parameters better then Runtime#exec.
String command = "/Applications/MiKTeX Console.app/Contents/bin/miktex-pdftex";
String outputDir = System.getProperty("user.dir");
String sourceFile = "Sample.tex";
List<String> commands = new ArrayList<>();
commands.add(command);
commands.add("--interaction=nonstopmode");
commands.add("--output-directory=" + outputDir);
commands.add(sourceFile);
So the above is very simple...
The command I want to run is /Applications/MiKTeX Console.app/Contents/bin/miktex-pdftex (I'm running on MacOS and I couldn't get the command installed outside the application bundle)
I want the output-directory to be the same as the current working directory (System.getProperty("user.dir")), but you could supply what every you need
I'm running in "nonstopmode" (--interaction=nonstopmode) because otherwise I would be required to provide input, which is just more complex
And my input file (Sample.tex) which is also in the working directory.
Next, we build the ProcessBuilder and redirect the error stream into the InputStream, this just reduces the next to read these two streams separately...
ProcessBuilder pb = new ProcessBuilder(commands);
pb.redirectErrorStream(true);
Next, we run the command, read the contents of the InputStream (otherwise you can stall the process), you can do what ever you want with this, I've just echoed it to the screen
try {
Process process = pb.start();
InputStream is = process.getInputStream();
int in = -1;
while ((in = is.read()) != -1) {
System.out.print((char)in);
}
int exitValue = process.waitFor();
System.out.println("");
System.out.println("Did exit with " + exitValue);
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
}
The use int exitValue = process.waitFor(); here is just to ensure that command has completed and get the exit value it generated. Normally, 0 is success, but you'd need to read the documentation of the command to be sure

How to run .sh file, using process builder?

I already create the .sh file, and the inside is:
sudo iptables --flush
sudo iptables -A INPUT -m mac --mac-source 00:00:00:00:00:00 -j DROP
It works normally when I run it on the terminal, but when I use processbuilder, it didn't do anything. No error, but didn't happen anything, this is the code on my java:
Process pb = new ProcessBuilder("/bin/bash","/my/file.sh").start();
I already looking for the answer, but I still failed to run the .sh file, even I do the same thing with people that already done it.
Sorry if this is a bad question, thank you.
Are you sure that the bash is not run? Do you checked the Process object returned by the startmethod? You can get the output value, the output stream, etc. from this objects.
Check your streams and exitvalue for errors... sudo is probably the problem here.
Not necessarily the best code but it gets the job done. Executes a process, takes the process.streams and prints them to System.out. Might helpt to find out what the issue actually is atlest.
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(true);
final Process proc = pb.start();
final StringBuilder builder = new StringBuilder("Process output");
final Thread logThread = new Thread() {
#Override
public void run() {
InputStream is = proc.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
try {
String line;
do {
line = reader.readLine();
builder.append("");
builder.append(line == null ? "" : line);
builder.append("<br/>");
} while(line != null);
} catch (IOException e) {
builder.append("Exception! ").append(e.getMessage());
} finally {
try {
reader.close();
} catch (IOException e) {
builder.append("Exception! ").append(e.getMessage());
}
}
}
};
logThread.start();
int retVal = proc.waitFor();
System.out.println(builder.toString());
From Java API Runtime : http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html
// Java runtime
Runtime runtime = Runtime.getRuntime();
// Command
String[] command = {"/bin/bash", "/my/file.sh"};
// Process
Process process = runtime.exec(command);
Also you should be careful with sudo commands that may ask for root password.

cmd open and close immediately while opening java

I am creating a code editor for Java source files by using Java. When I click on the RUN menu, it perfectly opens cmd and run javac command, but the problem is that it immediately gets closed and I want something like pause.
This is my code:
Runtime rt = Runtime.getRuntime();
try {
rt.exec("cmd.exe /c start java Maq");
} catch (IOException e1) {
e1.printStackTrace();
}
How to get rid of this problem?
Now that you have confirmed that you actually need javac and are working on an IDE/editor, the right way to handle compiling errors is by compiling from the JRE using javax.tools.JavaCompiler.
The JavaCompiler gives you refined control, cross platform functionality and is always there. You can take a look at the JavaDoc to get yourself started. Here's a nice example of its usage.
I have used it personally for an IDE like project and it did exactly what you would expect from an in-program compiler.
The 'start' bit of your command detaches Java from the cmd process.
You're probably best off writing a batch script containing something like this:
#echo off
java Maq
pause
Then just call that batch file using Runtime.exec(...)
Answer from this question helped me :)
Runtime rt = Runtime.getRuntime();
try {
rt.exec("cmd.exe /c cd /d d: & start cmd.exe /k javac Maq.java");
} catch (IOException e1) {
e1.printStackTrace();
}
To see javac's output, you can't use Runtime.exec(). Use a ProcessBuilder instead. Your code can look something like this:
ProcessBuilder pb = new ProcessBuilder("javac", "Maq.java");
pb.directory(new File("/path/to/source/code/"));
Process p = pb.start();
InputStream in = p.getInputStream(); // this is connected to the System.out from javac
int exit = p.waitFor(); // wait for javac to finish
StringBuilder text = new StringBuilder();
char[] buf = new char[1024]; int read;
while ((read = in.read(buf)) != -1)
text.append(new String(buf, 0, read));
text.append("\n\njavac returned with exit code ").append(exit);
// display text - it now contains javac's output and its exit code
JFrame f = new JFrame("javac's output");
JTextPane tp = new JTextPane();
tp.setText(text.toString());
tp.setEditable(false);
f.setContentPane(tp);
f.setSize(500, 400); // or whatever
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setVisible(true);

Categories

Resources