Runtime.exec not running the "find" command - java

My problem is that, i am using Runtime.getruntime.exec() function to run my unix command on Java. But, it jumps to the end of codes while exec() command is being run. The codes are below.
Process songProcess;
ArrayList<String> xmlFilePathsForEmi = new ArrayList<String>();
int countForEmiSongUpdates = 0;
String line;
try {
songProcess = Runtime.getRuntime().exec(new String[]{"find /home/gozenem/emiornek/ -name '*.xml'"}); // It jumps here !
songProcess.waitFor();
bufferedReaderSong = new BufferedReader(new InputStreamReader(songProcess.getInputStream()));
while((line = bufferedReaderSong.readLine()) != null){
xmlFilePathsForEmi.add(line);
}
...
...
...
}
I do not know what it is related to, may be there is a character that exec function could not run. I need your precious help. Thank you.

Your String[] parameter to Runtime.exec() is incorrect. It must be split up so that it contains one element per item (the executable must be one string, then each individual argument must come in its own string).
Try something like:
songProcess = Runtime.getRuntime().exec(new String[]{"find", "/home/gozenem/emiornek/", "-name", "*.xml"});
Also calling waitFor where you are doing isn't appropriate. You need to read the output while the process is running, otherwise you risk filling up the I/O buffers that are used between the Java VM and your process. So move that waitFor to after you've processed the output.
From the Process docs:
By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, [...]. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.

Related

How to get command prompt output in java?

How to get the output of the command prompt which means i have opend a command prompt like this.
Process process = Runtime.getRuntime().exec("cmd /c start cmd.exe /K \"C:\\Editor\\editorTemp.exe\"");
i can not get the cmd output like this
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
So how can i get the command prompt output ?
This is not Java question. Basically what you doing is running Java (Java Main Process A) and from it starting another process (Windows CMD B). This is fine and you can get input/output streams of this process (B) in Java(A).
However this process (B) starts another process (again Windows CMD C) with its own standard input/output. This process has nothing common with processes A&B and uses Windows' standard Input/Output streams. So, there are no connections between A and C.
I'm not sure but I think there are some ways to run Windows CMD with different or not standard IO. Maybe something like this will work:
cmd <tty >tty
but there is no tty in Windows. Pragmatically you can do this as described here - Creating a Child Process with Redirected Input and Output but that would not work for regular CMD.
Nevertheless it became even more problematic when you start your own process from the editorTemp.exe (process D). D has even more disconnection with process A. And all for what? What don't you simply start process D directly from A and have full control on the IO streams and process itself?
Here is good example how to do so.
Your java thread is working independently of CMD call. The java code is beating the STDOUT pipe before anything is written.
If you call Process.waitFor(), it will wait until the CMD call is done. The STDOUT should be in the buffer, and then you can read it.
When you do a readLine(), your java thread is blocked until you have an actual full line or the input stream is closed.
If the program prints a partial line (without CR or LF at the end), and then waits for input, the readLine will be stuck.
So you will need to read character by character, until you think the proces has no more things to say.
See e.g. Is it possible to read from a InputStream with a timeout?
import java.util.Scanner;
Inside the main write this.
Scanner output = new Scanner(System.in);
System.out.println(“Enter your name”);
String name = output.next();
If you want user to enter an int then you need to do this.
int number = output.nextInt();

Getting too many arguments error while executing tr command from java

file = D:\Unix\tr.exe "Æ" "~" < "C:\SourceFiles\source.csv" > "D:\tgt"
When i execute this command using the below code in java
Process process = Runtime.getRuntime().exec(file);
am getting the following error
D:\Unix\tr.exe: too many arguments
PS : File contains Æ characters am trying to replace all those characters with ~
Any suggestions please ?
You're passing unicode in the CMD, I guess that causes the problem.
Set chcp xxx on the CMD and try.
refer below link for chcp codes
https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/chcp.mspx?mfr=true
You have to program the io redirection yourself. This is usually the bash that takes care of it.
The result of the exec() call is a process. This process can then be used to get the STDIN of the process. Send the data to that process using that stream.
The way you call it, you send another command line option to tr, which is the < and > redirectors and the filenames.
Process process = System.getRuntime().exec(strBatchFileName);
OutputStream stdin = process.getOutputStream();
sendFileToStream(out);
InputStream stdout = process.getInputStream();
loadResultFromStream(stdout);
This is a pseudocode example, where sendFileToStream(...) feeds the input file into the TR process, and the loadResultFromStream(...) will load the result.
You may need to utilize threads to feed and read if the data is larger than the stream's buffer.
The question is kind of a duplicate and you will find a ProcessBuilder example here: Runtime's exec() method is not redirecting the output

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.

Why does java.lang.process's readline() behave differently for reading inputstream on different boxes with the same os

I tested this code(below) on several different linux boxes(4+) and it worked fine. However, on one linux box I ran into an issue with readline() hanging for the error inputStream(errorStream). This stream should be empty so I suspected that box was not writing out a line terminator to the errorStream for the error. I changed my code to use read() instead of readline()...but read() also hung.
I tried retrieving the input inputStream first, and that worked and there was no hangs with readline()/read() for the error inputstream. I could not do this since I needed to obtain possible errors first. Appearing to be a deadlock, I was able to resolve this by having each inputstream read from it's own thread. Why did I only see this issue on one box? Is there a kernel setting or some other setting specific to this box that could have caused this?
ProcessBuilder processBuilder = new ProcessBuilder()
try
{
Process processA = null;
synchronized (processBuilder)
{
processBuilder.command("/bin/sh","-c"," . /Home/SomeScript.ksh");
processA = processBuilder.start();
}
inputStream = processA.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
errorStream = processA.getErrorStream();
errorReader = new BufferedReader(new InputStreamReader(errorStream));
String driverError;
while ((driverError = errorReader.readLine()) != null)
{
//some code
}
Why did I only see this issue on one box?
Most likely because of something in the script that is being run ... and its interactions with its environment (e.g. files, environment variables, etc)
Is there a kernel setting or some other setting specific to this box that could have caused this?
It is possible but unlikely that it is a kernel setting. It might be "something else". Indeed, it has to be "something" outside of the Java application that is to blame, at least in part.
I suggest you do the following temporarily (at least):
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("/bin/sh","-c"," . /Home/SomeScript.ksh");
processBuilder.redirectErrorStream(true);
processA = processBuilder.start();
inputStream = processA.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
System.out.println("Return code is " + processA.exitValue());
That way you can see what all of the output is.
There should not be a problem if the external process fails to put a newline at the end of the last line. The Java process will see an EOF on the input stream, and the BufferedReader will return what characters it has ... and return null on the next call.
Another possibility is that the external process is blocking because it is trying to read from its standard input.
UPDATE
The redirectErrorStream also resolved the issue, but I need the error stream separate.
OK so if it did (reliably) solve the problem then that (most likely) means that you have to read the external processes stdout and stderr streams in parallel. The simple way to do is to create 2 threads to read and buffer the two streams separately. For example: Capturing stdout when calling Runtime.exec
(Your problem is due to the fact that pipes have a finite buffering capacity. The external problem is most likely alternating between writing stuff to stdout and stderr. If it tries to write to one of the pipes when that pipe is "full", it will block. But if your application is reading all of the other pipe (to EOF) before it reads the blocked pipe, then everything will deadlock. The fact that the external process is stuck in PIPE_W state is more evidence for this explanation.
One possible reason that you are seeing different behaviour on different systems is that the amount of buffering in a pipe is system dependent. But it could also be due to differences in what the external process is doing; e.g. its inputs.)
You are running OS specific commands in a script, any one could be holding the error output. You can avoid this by discarding the errors, but that is unlikely to be a good idea.
I would check the version of the OS are the same and whether you have any significant differences in the command you run in the script. If this doesn't help, take out commands from the script until it starts working. I assume an empty script doesn't do this.

call lynx from jsp script

I have an execute(String cmd) in a jsp script that calls the exec method from the Runtime class.
It works when I call a local command, like a php script stored on the server. for example: /usr/bin/php /path/to/php/script arg1 arg2
So I guess my execute command is ok, since it is working with that.
Now when I try to call lynx, the text-based web browser, it does not work.
If I call it in a terminal, it works fine:
/usr/bin/lynx -dump -accept_all_cookies 'http://www.someurl.net/?arg1=1&arg2=2'
But when I call this from my execute command, nothing happens...
Any idea why?
This is my execute method:
public String execute(String cmd){
Runtime r = Runtime.getRuntime();
Process p = null;
String res = "";
try {
p = r.exec(cmd);
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader br = new BufferedReader(isr);
String line = null;
//out.println(res);
while ((line = br.readLine()) != null) {
res += line;
}
p.waitFor();
} catch (Exception e) {
res += e;
}
System.out.println(p.exitValue());
return res;
}
You need to read from the Process' output stream.
Since you're not, the underlying lynx process is likely blocking while writing output, waiting for someone to empty the output stream's buffer. Even if you're going to ignore the output, you need to read it anyway for the process to execute as you'd expect.
As the javadocs of Process say, "Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock."
See http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html for some examples of how to handle this.
Edit: in case you are wondering, chances are that when you invoked the PHP script it didn't produce a great deal of output, and so was able to terminate before filling the output buffer and blocking. The lynx command is presumably producing more output and hence hitting this issue.
I solved it.... by calling lynx into a php script, php script that I called from the Jsp script...
It's a shitty solution but at least it works... I still do not really understand why the exec command from Java works that way...
Thanks for your help anyway Andrzej (Czech I guess from the name..? ^_^), somehow you put me on the way!

Categories