Problems with running command line from Java - java

I've been trying to run a compiled C program from Java using following commnand. Then I want to get results from process' input stream.
Process p = Runtime.getRuntime().exec(commandLine);
Now, my command is this (first string is path to program, second and third are paths to files, which program takes as params):
trec_eval.8.1\trec_eval.exe trec_eval.8.1\czech TREC\results_2016-04-26_20_52_175.txt
When I run it normally from command line (I'm on Windows 10), it works as expected (C program finishes without errors and prints expected output into the command line), but alas, when I run it from Java, it doesn't work. Both stdout and stderr streams of the process are empty and process' exit status is some error code.
Here is minimal "working" example (I omitted stderr stream, since it made this code snippet too long):
String commandLine = "trec_eval.8.1\\trec_eval.exe" +
" trec_eval.8.1\\czech + " " + file;
System.out.println("Command: " + commandLine);
Process process = Runtime.getRuntime().exec(commandLine);
BufferedReader stdout = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder output = new StringBuilder("Output:\n");
for (String line; (line = stdout.readLine()) != null; ) {
output.append(line).append("\n");
}
System.out.println(output.toString());
int exitStatus = 0;
try {
exitStatus = process.waitFor();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
System.out.println("Exit status: " + exitStatus);
stdout.close();
Output from this code are following lines:
Command: trec_eval.8.1\trec_eval.exe trec_eval.8.1\czech TREC\results_2016-04-27_18_27_585.txt
Output:
Exit status: -1073741515
Obviously, I have read several other answers here on Stackoverflow and elsewhere. Unfortunately, code in said answers was pretty much the same as mine (and did not work for me in the same way as my code does not work).
Can someone please tell me, what am I doing wrong? Why is stdout stream empty instead of containing C program's output? Why does not the process exit with status 0 (as it should), but with before-mentioned monstrosity? Finally, if you know, why my Java code does not work as expected, can you explain, why the exact same command works from the the command line?
Thanks in advance.

It seems like the program is not getting something it needs in it's environment. You said the program exited with an error code--so that sounds like your Java code is doing exactly what it should be doing (Starting the program and reading the exit code).
Your paths look relative--perhaps Java isn't starting in the directory you think it is? Try doing a full path to your argument and see if that helps.
Is there a way you can interpret the error code from the app?
If all else fails, try running it through a shell (either cmd /c or sh depending on your OS) using full paths. You can test that without java, then pass the whole thing to java and see if you get the same results.

Related

Execute command from Java

I'm trying to execute a script from Java program:
public class TestCommandLine
{
public static void main (String[] args)
{
String PATH = "/path/programs/";
String command = PATH + "name_programs param1 param2";
executeCommand (command);
}
private static String executeCommand (String command)
{
StringBuffer output = new StringBuffer();
String line = "";
Process p;
try {
p = Runtime.getRuntime ().exec (command);
p.waitFor ();
BufferedReader reader = new BufferedReader (new InputStreamReader (p.getInputStream ()));
while ((line = reader.readLine ()) != null) {
output.append (line + "\n");
}
}
catch (Exception e) {
e.printStackTrace ();
}
return output.toString ();
}
}
there is not error, but the program does not run. I also try others solutions from stackoverflow but all of them didn't work
If you'd given your actual command to start with, this would have been much quicker.
You cannot use Process.exec to run shell-interpreted commands. Instead it executes programs directly. Thus input/output redirection (|, >, etc.) is not possible.
If you actually read the stderr (getErrorStream()) output it would probably be along the lines of "invalid argument: >".
You will either have to:
Redirect the output in Java. Read from the process's stdout (getInputStream()) and write to a FileOutputStream of some kind.
Execute a shell instead of your command directly. For example /bin/sh -c "command arg > file". The quoted section must be passed to sh as a single argument. In this case you wouldn't be able to see anything in stdout, and would have to open and read the file you just wrote to. The first option is probably more sensible.
And as pointed out elsewhere, unless your expecting a very small amount of output, you shouldn't wait for the command to exit before consuming the streams.
The only time I've done it I've used something like this:
Process p = Runtime.getRuntime().exec("foo.exe");
Have you tried that? If so, what was the error you got back?
Your command is producing output that you want to read, but you refuse to read any of it until the command has finished producing it all and has exited (not calling getInputStream() until after waitFor()).
If your command doesn't produce much output, this is OK, Java can buffer it. But if your command produces a lot of output, Java can't buffer it all, and the command gets blocked.
The operating system won't let the command write any more output because Java's buffer is full and you haven't instructed Java to empty it. So the program is blocked, and Java's waitFor() will never come back.
To solve your problem, you should call getInputStream() immediately after getting the Process object back from exec(), and you should create a new Thread that is responsible for reading the command output into your StringBuffer.
You should then waitFor() the process to finish, to see if it exited successfully, and then you can wait for the thread to get to the end of the inputstream and finish - at that point, it is safe to read through the StringBuffer with the full output from your command.

How to know whether SFTP was successful or not in WinSCP

I am using below code to run SFTP command through Jsch:
public void putfile(){
try {
String command="winscp /script=D:\\command.txt" ;
System.out.println(command);
Runtime rt=Runtime.getRuntime();
rt.exec(command);
}
catch(Exception e) {
System.out.println("Exception in index.jsp:"+e.getMessage());
}
}
I am putting sample.zip from local machine to Unix Server,
The command.txt contains:
option confirm off
open sftp:User:password#IP
get G:\sample.zip /MyFolderLocation/
exit
Its working fine but i am not getting any exception whenever the SFTP process fails.Is there any way to handle it?
There are two common ways to detect whether a subprocess you ran encountered an error:
check its exit code,
see if it writes any error messages to standard output or standard error.
I don't know whether WinSCP sets an exit code in the event of an error, or writes a message to standard output or standard error, but it should do at least one of them. (It may even do both, which is what I'd expect all well-behaved processes to do.) You'll just have to try out WinSCP and see what happens.
I'd also recommend using a ProcessBuilder instead of Runtime.getRuntime().exec(...) to run the command. If nothing else, this allows you to redirect standard error into standard output so you only have one stream to read from.
Here's what your code looks like after I've modified it to use a ProcessBuilder, get the process's exit code and read the output from the command into a string:
public void putfile() {
try {
ProcessBuilder builder = new ProcessBuilder("winscp", "/script=D:\\command.txt");
builder.redirectErrorStream(true);
Process process = builder.start();
// read output from the process
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder outputBuilder = new StringBuilder();
String line;
do {
line = reader.readLine();
if (line != null) { outputBuilder.append(line).append('\n'); }
} while (line != null);
reader.close();
String output = outputBuilder.toString();
// inspect output for error messages.
int exitCode = process.waitFor();
// see if exit code is 0 (success) or != 0 (error)
}
catch(Exception e) {
System.out.println("Exception in index.jsp:"+e.getMessage());
}
}
Of course, reader should be closed in a finally block. For clarity I haven't bothered doing this in the code above.
Note that when running a subprocess in Java you should always read the subprocess's output, even if you don't care about its contents. If you don't, the buffer that the output gets written into may fill up, which will cause the subprocess to hang if it wants to write any more.
See WinSCP FAQ How do I know that script completed successfully?
You can tell the result of script by WinSCP exit code. Code 0
indicates success, while 1 indicates an error. For more details refer
to scripting documentation.
Batch script (specified using /script or /command command-line switches) terminates with code 1 immediately once any error occurs.
To find out why the script failed, inspect session log.
For an example see guide to transfer automation.

Starting a process from a Java application

I know more or less how to do this, but I think I'm getting burned by the complexity of this command due to inexperience.
I'm trying to feed some raw html into wkhtmltopdf. I can do this from the command line like this:
echo "<p>Hello</p>" | wkhtmltopdf - ~/somePdf.pdf
That works fine, but how do I do this from a Java app? Here's a couple things I've tried:
String[] cmd = { "echo", html.body(), "|", "wkhtmltopdf", "-", "/home/sam/yourPdf.pdf" };
Runtime.getRuntime().exec(cmd);
OR
Runtime.getRuntime().exec("echo " + html.body() + " | wkhtmltopdf - /home/sam/yourPdf.pdf");
Neither one of these produces a file in my home folder.
I've read that wkhtmltopdf will output to STDERR, but I'm not sure how to view that from Eclipse. I was told it should be available in my Console view, but I don't see anything there.
Any help is appreciated, thanks!
Edit
The accepted answer will work for wkhtmltopdf, but for anyone else using the Play! framework who finds this post, there is a Play! module that generates a PDF based on a scala template. It works really well, but don't forget to set media="print" in your stylesheet :)
You cannot do this directly, because you are running two commands and you create a pipe. Neither the Runtime.exec() nor the ProcessBuilder.command() methods are made for this. The easiest way to still achieve something akin to this from Java is to put all that stuff into a shell script and call that script with Runtime.exec() .
EDIT:
You can also skip the shell script and call
Runtime.getRuntime().exec( new String[] { "bash", "-c", "\"echo \"<p>Hello</p>\ | wkhtmltopdf - ~/somePdf.pdf\""} );
That save you writing the shell script, but you may have to fiddle with the quotes a little to get it right.
You can try something like this to output your error stream to your console:
try{
Runtime runTime= Runtime.getRuntime();
Process process= runTime.exec("echo " + html.body() + " | wkhtmltopdf - /home/sam/yourPdf.pdf");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
while ( (line = reader.readLine()) != null){
System.err.println(line);
}
}catch(Exception exe){
exe.printStackTrace();
}
Note that this is specific to getting what is printed to your error stream. I hope this helps to get you started

How can i run a .jar file in java

I'm making an update function for my project, it's working great, until i want it to restart, basically I download the new file and replace it with the old one, and then i want to run it again, now for some reason it doesn't wna run, and i don't get any error...
Here is the complete update class:
http://dl.dropbox.com/u/38414202/Update.txt
Here is the method i'm using to run my .jar file:
String currDir = new File("(CoN).jar").getAbsolutePath();
Process runManager = Runtime.getRuntime().exec("java -jar " + currDir);
It's not clear to me, why do you need to run the jar with a call to exec() . Given that you need to run the code in the .jar file from a Java program, you could simply run the main() method as defined in the jar's manifest, and capture its output - wherever that is.
Using exec() is OK when you need to call a program from the underlying operating system, but there are easier ways to do this if both the caller and the callee are Java programs.
Now, if your jar is gonna change dynamically and you need to update your program according to a new jar, there are mechanisms for reloading its contents, for instance take a look ath this other post.
The JavaDocs for the Process class specifically point out that if you don't capture the output stream of the Process and promptly read it that the process could halt. If this is the case, then you wouldn't see the process that you started run.
I think you have to capture the stream like this :
BufferedReader stdInput = new BufferedReader(new InputStreamReader(runManager.getInputStream()),8*1024);
BufferedReader stdError = new BufferedReader(new InputStreamReader(runManager.getErrorStream()));
// read the output from the command
String s = null;
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
The exec function doesn't automatically lookup into the PATH to start a process, so you have to pass the complete path for the java binary.
You can do that by using the java.home system property, see this answer: ProcessBuilder - Start another process / JVM - HowTo?
No one here seemed to help me, so I went to ask my friend and I had it almost right. It abiously required the string to be an array.
solution:
String[] cmd = {"java", "-jar", currDir};
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e1) {
e1.printStackTrace();
}

Java read Oracle EXP command output

I need to run the Oracle EXP command through a Java program and print somewhere the command output.
The EXP command is correct, the dump file is created correctly when I execute my Java code, but I'm experiencing some issues to get the output.
This is an snippet very similar to the one I'm using to read the output:
String line;
String output = "";
try {
Process p = Runtime.getRuntime().exec(myCommand);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
output += (line + '\n');
}
input.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
System.out.println(output);
As I said, the command is correctly executed (verified through the generated dump file), but nothing appears on my console and my Java programs doesn't terminate either.
The same code works perfectly if I use another command, as "ls -l" instead of "exp ...".
Maybe exp is writing to standard error output rather than standard output.
Try to use p.getErrorStream() instead of getInputStream()
As a_horse_with_no_name said, it might be that the error stream buffer is full and thus is blocking the programm execution.
Either try to start a Thread to also read the error stream or use the ProcessBuilder class to redirect the error stream to stdout (which you already read).

Categories