Runtime.exec(cmd) hangs up

V

Vic

I am having a problem with Runtime.exec(cmd) where cmd is a string and
is as follows -

cmd = "home/qaplay/loader/604/soaploaderclient.ps nemo 50624 55604
genevaman qa /home/vpatanka/604Current/lib/loader/data/
DuplicateTransactionTest.0.lrd -bcp > & $GVHOME/tempOut.txt"


The actual code is like this ->
public CommandExecuter (String cmd) throws java.io.IOException{
System.out.println("CommandExecuter: EXECUTING COMMAND: "+cmd);
Process proc = Runtime.getRuntime().exec(cmd);

BufferedReader in = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
BufferedReader err = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));

stdout = "";
while ((line = in.readLine()) != null)
stdout += line +"\n";
if (stdout == "")
stdout = null;

stderr = "";
while ((line = err.readLine()) != null)
stderr += line +"\n";
if (stderr == "")
stderr = null;

//System.out.println ("CommandExecuter stdout="+stdout);
//System.out.println ("CommandExecuter stderr="+stderr);
}
}

I can run the same cmd on the shell and I get a an output which is
pretty big so I am not copying it over here but if you guyz need it
then I can do that. Please let me know what am I missing here in
Runtime.exec() or its something else
 
V

Vic

one correction -
cmd = "home/qaplay/loader/604/soaploaderclient.ps nemo 50624 55604
genevaman qa /home/vpatanka/604Current/lib/loader/data/
DuplicateTransactionTest.0.lrd -bcp"
 
V

Vic

type
cmd = "home/qaplay/loader/604/soaploaderclient.ps nemo 50624 55604
genevaman qa /home/vpatanka/604Current/lib/loader/data/
DuplicateTransactionTest.0.lrd -bcp"
 
M

Matt Humphrey

|I am having a problem with Runtime.exec(cmd) where cmd is a string and
| is as follows -
|
| cmd = "home/qaplay/loader/604/soaploaderclient.ps nemo 50624 55604
| genevaman qa /home/vpatanka/604Current/lib/loader/data/
| DuplicateTransactionTest.0.lrd -bcp > & $GVHOME/tempOut.txt"
|
|
| The actual code is like this ->
| public CommandExecuter (String cmd) throws java.io.IOException{
| System.out.println("CommandExecuter: EXECUTING COMMAND: "+cmd);
| Process proc = Runtime.getRuntime().exec(cmd);
|
| BufferedReader in = new BufferedReader(new
| InputStreamReader(proc.getInputStream()));
| BufferedReader err = new BufferedReader(new
| InputStreamReader(proc.getErrorStream()));
|
| stdout = "";
| while ((line = in.readLine()) != null)
| stdout += line +"\n";
| if (stdout == "")
| stdout = null;
|
| stderr = "";
| while ((line = err.readLine()) != null)
| stderr += line +"\n";
| if (stderr == "")
| stderr = null;

The first thing that I see is that your command contains io redirection.
You have to invoke a shell in order to use those operators--you don't get
one automatically. Also, you can find the details elsewhere on the web or
the cljp past messages, but reading stdout and then reading stderr will not
solve the blocking problem. Both must be read simultaneously because if
either fills up its OS pipe buffer, your exec cmd will be automatically
suspended to give your Java reader a chance to empty the buffer. However,
your Java program will be waiting for output which will never arrive. In
this case, the stderr buffer could fill up and suspend the process while
your Java program waits for more output. There are a variety of tools and
techniques to help with this nowadays.

Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
V

Vic

Matt,
Thanks for a reply. I actually typed cmd incorrectly which I fixed in
the same post later on. sorry about that

cmd = ""home/qaplay/loader/604/soaploaderclient.ps nemo 50624 55604
genevaman qa /home/vpatanka/604Current/lib/loader/data/
DuplicateTransactionTest.0.lrd -bcp"

I think I know what you are talking about. Are you talking about
StreamGobbler or something of that sort? I did google it for my
problem and saw a few posts talking about it so just wondering.
I'll try it out n will get back to you soon. Thanks
 
M

Mike Schilling

Vic said:
I am having a problem with Runtime.exec(cmd) where cmd is a string and
is as follows -

cmd = "home/qaplay/loader/604/soaploaderclient.ps nemo 50624 55604
genevaman qa /home/vpatanka/604Current/lib/loader/data/
DuplicateTransactionTest.0.lrd -bcp > & $GVHOME/tempOut.txt"


The actual code is like this ->
public CommandExecuter (String cmd) throws java.io.IOException{
System.out.println("CommandExecuter: EXECUTING COMMAND: "+cmd);
Process proc = Runtime.getRuntime().exec(cmd);

BufferedReader in = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
BufferedReader err = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));

stdout = "";
while ((line = in.readLine()) != null)
stdout += line +"\n";
if (stdout == "")
stdout = null;

stderr = "";
while ((line = err.readLine()) != null)
stderr += line +"\n";
if (stderr == "")
stderr = null;

//System.out.println ("CommandExecuter stdout="+stdout);
//System.out.println ("CommandExecuter stderr="+stderr);
}
}

I can run the same cmd on the shell and I get a an output which is
pretty big so I am not copying it over here but if you guyz need it
then I can do that. Please let me know what am I missing here in
Runtime.exec() or its something else


The obvious issue is that this code won't start to read stderr until the
exec'd process closes stdout, so the process may be hung trying to wite to
stderr. Try reading from stdout and stderr at the same time (in different
threads.) A nice, symmetrical way to do this is

1. Runtime.exec()
2. Start a thread that reads from stdout as long as there's anything to
read and then exits.
3. Start another thread that reads from stderr as long as there's
anything to read and then exits.
4. Process.waitFor();
 
V

Vic

I was wondering if its possible to read only stdout as a temporary fix
if its gonna work, would this hang up problem be still there if I just
do

Process proc = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
proc.waitfor (in the try catch block)
.........
.........

I actually tried the above version but didn't work
 
D

Daniel Pitts

I was wondering if its possible to read only stdout as a temporary fix
if its gonna work, would this hang up problem be still there if I just
do

Process proc = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
proc.waitfor (in the try catch block)
........
........

I actually tried the above version but didn't work
[snip];

You cant just waitFor, you actually have to actively read both stdout
and stderr. Although, if you don't care about distinguishing one from
the other, there IS an option (using ProcessBuilder I think) to
combine both into a single stream. You can then just read from that
stream and be happy with your results.
 
V

Vic

Alright so here is my new code now, I implemented it the way you said
(with some online help)
class StreamGobbler extends Thread {
InputStream is;
String type;

StreamGobbler(InputStream is, String type){
this.is = is;
this.type = type;
}

public void run(){
try{
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while((line = br.readLine()) != null){
System.out.println(type+">"+line);
}
}
catch(IOException ioe){
ioe.printStackTrace();
}
}
}

class CommandExecuter {
public static String stdout = null;
public static String stderr = null;
private String line;

public CommandExecuter (String cmd) throws java.io.IOException{
System.out.println("CommandExecuter: EXECUTING COMMAND: "+cmd);
Process proc = Runtime.getRuntime().exec(cmd);

StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(),"ERROR");
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(),"OUTPUT");

errorGobbler.start();
outputGobbler.start();

try{
//VicP - temporary code to check the process status
int val = proc.waitFor();
//proc.wait(120000);
}
catch (Throwable t){
t.printStackTrace();
}
}
}
But now the question is how do I set the value of stdout and stderr in
CommandExecuter(As we are doing the stuff in thwo different threads
now)? I need these values as they are checked in the calling function
(which calls the Command executer constructor). Could you please
suggest me some changes to get this?
 
M

Mike Schilling

Vic said:
Alright so here is my new code now, I implemented it the way you said
(with some online help)
class StreamGobbler extends Thread {
InputStream is;
String type;

StreamGobbler(InputStream is, String type){
this.is = is;
this.type = type;
}

public void run(){
try{
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while((line = br.readLine()) != null){
System.out.println(type+">"+line);
}
}
catch(IOException ioe){
ioe.printStackTrace();
}
}
}

class CommandExecuter {
public static String stdout = null;
public static String stderr = null;
private String line;

public CommandExecuter (String cmd) throws java.io.IOException{
System.out.println("CommandExecuter: EXECUTING COMMAND: "+cmd);
Process proc = Runtime.getRuntime().exec(cmd);

StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(),"ERROR");
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(),"OUTPUT");

errorGobbler.start();
outputGobbler.start();

try{
//VicP - temporary code to check the process status
int val = proc.waitFor();
//proc.wait(120000);
}
catch (Throwable t){
t.printStackTrace();
}
}
}
But now the question is how do I set the value of stdout and stderr in
CommandExecuter(As we are doing the stuff in thwo different threads
now)? I need these values as they are checked in the calling function
(which calls the Command executer constructor). Could you please
suggest me some changes to get this?

Have your StreamGobbler class keep track of the characters it's read, much
as your original code did, and add a method to return the result, something
like (not tested or even compiled)

class StreamGobbler extends Thread {
InputStream is;
String type;
String read;

StreamGobbler(InputStream is, String type){
this.is = is;
this.type = type;
}

public String getResult() {
return result;
}

public void run(){
StringBuffer buffer = new StringBuffer();
try{
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while((line = br.readLine()) != null){
buffer.append(line);
buffer.append("\n");
}
}
catch(IOException ioe){
ioe.printStackTrace();
}
finally {
result = buffer.toString();
}
}
}

In the main program, do the following:

// wait for process to stop
int val = proc.waitFor();
// wait for threads to finish reading output
outputGobbler.join();
errorGobbler.join();
// get output
stdout = outputGobbler.getResult();
stderr = errorGobbler.getResult();
 
M

Matt Humphrey

| Alright so here is my new code now, I implemented it the way you said
| (with some online help)
| class StreamGobbler extends Thread {
| InputStream is;
| String type;
|
| StreamGobbler(InputStream is, String type){
| this.is = is;
| this.type = type;
| }
|
| public void run(){
| try{
| InputStreamReader isr = new InputStreamReader(is);
| BufferedReader br = new BufferedReader(isr);
| String line = null;
| while((line = br.readLine()) != null){
| System.out.println(type+">"+line);
| }
| }
| catch(IOException ioe){
| ioe.printStackTrace();
| }
| }
| }
|
| class CommandExecuter {
| public static String stdout = null;
| public static String stderr = null;
| private String line;
|
| public CommandExecuter (String cmd) throws java.io.IOException{
| System.out.println("CommandExecuter: EXECUTING COMMAND: "+cmd);
| Process proc = Runtime.getRuntime().exec(cmd);
|
| StreamGobbler errorGobbler = new
| StreamGobbler(proc.getErrorStream(),"ERROR");
| StreamGobbler outputGobbler = new
| StreamGobbler(proc.getInputStream(),"OUTPUT");
|
| errorGobbler.start();
| outputGobbler.start();
|
| try{
| //VicP - temporary code to check the process status
| int val = proc.waitFor();
| //proc.wait(120000);
| }
| catch (Throwable t){
| t.printStackTrace();
| }
| }
| }
| But now the question is how do I set the value of stdout and stderr in
| CommandExecuter(As we are doing the stuff in thwo different threads
| now)? I need these values as they are checked in the calling function
| (which calls the Command executer constructor). Could you please
| suggest me some changes to get this?

Your earlier example showed that you wanted to concatenate all the output
into a single string. If that's what you want to do, add a StringBuffer
instance variable to the StreamGobbler and have the read loop append each
line as you get it--rather than print it out. Modify the CommandExecuter to
assign its stdout / stderr instance variables with the stream gobbler
contents when the process has completed. After the executer completes, just
retrieve the values via get methods.

If you want to actually process the strings as they arrive, that's a bit
more complicated.

Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
V

Vic

| Alright so here is my new code now, I implemented it the way you said
| (with some online help)
| class StreamGobbler extends Thread {
| InputStream is;
| String type;
|
| StreamGobbler(InputStream is, String type){
| this.is = is;
| this.type = type;
| }
|
| public void run(){
| try{
| InputStreamReader isr = new InputStreamReader(is);
| BufferedReader br = new BufferedReader(isr);
| String line = null;
| while((line = br.readLine()) != null){
| System.out.println(type+">"+line);
| }
| }
| catch(IOException ioe){
| ioe.printStackTrace();
| }
| }
| }
|
| class CommandExecuter {
| public static String stdout = null;
| public static String stderr = null;
| private String line;
|
| public CommandExecuter (String cmd) throws java.io.IOException{
| System.out.println("CommandExecuter: EXECUTING COMMAND: "+cmd);
| Process proc = Runtime.getRuntime().exec(cmd);
|
| StreamGobbler errorGobbler = new
| StreamGobbler(proc.getErrorStream(),"ERROR");
| StreamGobbler outputGobbler = new
| StreamGobbler(proc.getInputStream(),"OUTPUT");
|
| errorGobbler.start();
| outputGobbler.start();
|
| try{
| //VicP - temporary code to check the process status
| int val = proc.waitFor();
| //proc.wait(120000);
| }
| catch (Throwable t){
| t.printStackTrace();
| }
| }
| }
| But now the question is how do I set the value of stdout and stderr in
| CommandExecuter(As we are doing the stuff in thwo different threads
| now)? I need these values as they are checked in the calling function
| (which calls the Command executer constructor). Could you please
| suggest me some changes to get this?

Your earlier example showed that you wanted to concatenate all the output
into a single string. If that's what you want to do, add a StringBuffer
instance variable to the StreamGobbler and have the read loop append each
line as you get it--rather than print it out. Modify the CommandExecuter to
assign its stdout / stderr instance variables with the stream gobbler
contents when the process has completed. After the executer completes, just
retrieve the values via get methods.

If you want to actually process the strings as they arrive, that's a bit
more complicated.

Matt Humphrey (e-mail address removed)://www.iviz.com/

I talked to my manager and she allowed me to make stdout and stderr as
"pulic static" (global) so I could directly access those in
StreamGobbler as I am producing the output in those two thrads.
Thank you so much for your help. have a great long weekend
 
M

Matt Humphrey

| >
| > | > | Alright so here is my new code now, I implemented it the way you said
| > | (with some online help)
| > | class StreamGobbler extends Thread {
| > | InputStream is;
| > | String type;
| > |
| > | StreamGobbler(InputStream is, String type){
| > | this.is = is;
| > | this.type = type;
| > | }
| > |
| > | public void run(){
| > | try{
| > | InputStreamReader isr = new InputStreamReader(is);
| > | BufferedReader br = new BufferedReader(isr);
| > | String line = null;
| > | while((line = br.readLine()) != null){
| > | System.out.println(type+">"+line);
| > | }
| > | }
| > | catch(IOException ioe){
| > | ioe.printStackTrace();
| > | }
| > | }
| > | }
| > |
| > | class CommandExecuter {
| > | public static String stdout = null;
| > | public static String stderr = null;
| > | private String line;
| > |
| > | public CommandExecuter (String cmd) throws java.io.IOException{
| > | System.out.println("CommandExecuter: EXECUTING COMMAND: "+cmd);
| > | Process proc = Runtime.getRuntime().exec(cmd);
| > |
| > | StreamGobbler errorGobbler = new
| > | StreamGobbler(proc.getErrorStream(),"ERROR");
| > | StreamGobbler outputGobbler = new
| > | StreamGobbler(proc.getInputStream(),"OUTPUT");
| > |
| > | errorGobbler.start();
| > | outputGobbler.start();
| > |
| > | try{
| > | //VicP - temporary code to check the process status
| > | int val = proc.waitFor();
| > | //proc.wait(120000);
| > | }
| > | catch (Throwable t){
| > | t.printStackTrace();
| > | }
| > | }
| > | }
| > | But now the question is how do I set the value of stdout and stderr in
| > | CommandExecuter(As we are doing the stuff in thwo different threads
| > | now)? I need these values as they are checked in the calling function
| > | (which calls the Command executer constructor). Could you please
| > | suggest me some changes to get this?
| >
| > Your earlier example showed that you wanted to concatenate all the
output
| > into a single string. If that's what you want to do, add a StringBuffer
| > instance variable to the StreamGobbler and have the read loop append
each
| > line as you get it--rather than print it out. Modify the
CommandExecuter to
| > assign its stdout / stderr instance variables with the stream gobbler
| > contents when the process has completed. After the executer completes,
just
| > retrieve the values via get methods.
| >
| > If you want to actually process the strings as they arrive, that's a bit
| > more complicated.
| >
| > Matt Humphrey (e-mail address removed)://www.iviz.com/
|
| I talked to my manager and she allowed me to make stdout and stderr as
| "pulic static" (global) so I could directly access those in
| StreamGobbler as I am producing the output in those two thrads.
| Thank you so much for your help. have a great long weekend

That's the kind of problem I've seen trip up others and there's no reason to
use a static variable in this case because it's equally easy and much safer
to make it an instance variable. Good luck with your program.

Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
L

Lew

Matt Humphrey wrote:
Vic said:
| I talked to my manager and she allowed me to make stdout and stderr as
| "pulic static" (global) so I could directly access those in
| StreamGobbler as I am producing the output in those two thrads.
| Thank you so much for your help. have a great long weekend

That's the kind of problem I've seen trip up others and there's no reason to
use a static variable in this case because it's equally easy and much safer
to make it an instance variable. Good luck with your program.

I have a real problem with programmers asking permission from managers about
such detailed code decisions. If your manager is such a good coder, why is
she in management?

If the programmer needs to ask a manager for programming advice, why aren't
they in management and far, far, far away from coding?

If you are a good enough programmer to deserve the job title you should be
telling the manager what the code needs, not asking; if you aren't, your job
shouldn't involve anything fancier than asking, "Would you like fries with that?"
 
V

Vic

| >
| >| > | Alright so here is my new code now, I implemented it the way you said
| > | (with some online help)
| > | class StreamGobbler extends Thread {
| > | InputStream is;
| > | String type;
| > |
| > | StreamGobbler(InputStream is, String type){
| > | this.is = is;
| > | this.type = type;
| > | }
| > |
| > | public void run(){
| > | try{
| > | InputStreamReader isr = new InputStreamReader(is);
| > | BufferedReader br = new BufferedReader(isr);
| > | String line = null;
| > | while((line = br.readLine()) != null){
| > | System.out.println(type+">"+line);
| > | }
| > | }
| > | catch(IOException ioe){
| > | ioe.printStackTrace();
| > | }
| > | }
| > | }
| > |
| > | class CommandExecuter {
| > | public static String stdout = null;
| > | public static String stderr = null;
| > | private String line;
| > |
| > | public CommandExecuter (String cmd) throws java.io.IOException{
| > | System.out.println("CommandExecuter: EXECUTING COMMAND: "+cmd);
| > | Process proc = Runtime.getRuntime().exec(cmd);
| > |
| > | StreamGobbler errorGobbler = new
| > | StreamGobbler(proc.getErrorStream(),"ERROR");
| > | StreamGobbler outputGobbler = new
| > | StreamGobbler(proc.getInputStream(),"OUTPUT");
| > |
| > | errorGobbler.start();
| > | outputGobbler.start();
| > |
| > | try{
| > | //VicP - temporary code to check the process status
| > | int val = proc.waitFor();
| > | //proc.wait(120000);
| > | }
| > | catch (Throwable t){
| > | t.printStackTrace();
| > | }
| > | }
| > | }
| > | But now the question is how do I set the value of stdout and stderr in
| > | CommandExecuter(As we are doing the stuff in thwo different threads
| > | now)? I need these values as they are checked in the calling function
| > | (which calls the Command executer constructor). Could you please
| > | suggest me some changes to get this?
| >
| > Your earlier example showed that you wanted to concatenate all the
output
| > into a single string. If that's what you want to do, add a StringBuffer
| > instance variable to the StreamGobbler and have the read loop append
each
| > line as you get it--rather than print it out. Modify the
CommandExecuter to
| > assign its stdout / stderr instance variables with the stream gobbler
| > contents when the process has completed. After the executer completes,
just
| > retrieve the values via get methods.
| >
| > If you want to actually process the strings as they arrive, that's a bit
| > more complicated.
| >
| > Matt Humphrey (e-mail address removed)://www.iviz.com/
|
| I talked to my manager and she allowed me to make stdout and stderr as
| "pulic static" (global) so I could directly access those in
| StreamGobbler as I am producing the output in those two thrads.
| Thank you so much for your help. have a great long weekend

That's the kind of problem I've seen trip up others and there's no reason to
use a static variable in this case because it's equally easy and much safer
to make it an instance variable. Good luck with your program.

Matt Humphrey (e-mail address removed)://www.iviz.com/

Thanks Matt and everyone here for the info and help. I actually
modified the class and removed "static" and added getResult() in the
thread processing logic to get the string and then I access that in
the CommandExecuter class. Everything is working fine now.
Lew - no offense but you don't have to bash me up without knowing
anything about me. I have some experience with programming but I am in
QA/scripting side mostly doing perl scripts n other stuff but I was
asked to work on java code (there was a guy who left the company and
was working on this part) which I have hardly done so I am not a java
coder at all. But my manager just asked me to look into this if I
could thats why I started looking into the code. have a nice day
Vic
 
L

Lew

Vic said:
Lew - no offense but you don't have to bash me up without knowing
anything about me. I have some experience with programming but I am in
QA/scripting side mostly doing perl scripts n other stuff but I was
asked to work on java code (there was a guy who left the company and
was working on this part) which I have hardly done so I am not a java
coder at all. But my manager just asked me to look into this if I
could thats why I started looking into the code. have a nice day

I am not bashing you at all.

I was describing a general problem I have with certain types of manager and
the lack of respect they sometimes have for our profession.

I apologize for making it sound like you personally were at any kind of fault.
I should learn to use the pronoun "one" when prescribing, instead of the
less formal and more ambiguous "you".

I am aware that managers often tell us what to do instead of letting us tell
them what should be done. I do not blame the engineer for this. Again, I'm
sorry that I caught you in the crossfire.
 
V

Vic

I am not bashing you at all.

I was describing a general problem I have with certain types of manager and
the lack of respect they sometimes have for our profession.

I apologize for making it sound like you personally were at any kind of fault.
I should learn to use the pronoun "one" when prescribing, instead of the
less formal and more ambiguous "you".

I am aware that managers often tell us what to do instead of letting us tell
them what should be done. I do not blame the engineer for this. Again, I'm
sorry that I caught you in the crossfire.

No Problem. Its cool. Thanks for the clarification. I totally agree
with what you're saying. Have a nice day
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top