Link to home
Start Free TrialLog in
Avatar of courtenayt
courtenayt

asked on

Java InputStream hanging when executing a script for ftp

Hi,

I've got 2 scripts that I'm calling from my Java app via the Runtime process executor:

            Runtime rShell = Runtime.getRuntime();
            Process pExecution = rShell.exec(sCommand);

The commands call scripts that are used to log into ftp servers and either upload or download files.  In both scripts I'm also doing a remote listing of the file/s I either just uploaded or just downloaded so I can compare the number of bytes on the remote side with the number of bytes locally.  

The strange thing is when I try to get this info from the InputStream, it doesn't always give me all of the input and sometimes it hangs.  If I try to get the input stream multiple times, this sometimes helps to get all of the input, but I still run into issues with it hanging.  

The multiple input stream values appear to come into existence if my ftp script uses "ls" or "dir" commands.  Below is an example of my using the InputStream 2 times and storing everything from both InputStreams into a String called str_inputStream that I can later parse.  

            BufferedReader br = null;
            String line;
            
            // Capture any process output
            br = new BufferedReader(new InputStreamReader(pExecution.getInputStream()));
            line = "";
            str_inputStream = "";
            while ((line = br.readLine()) != null && br.ready()) {
                  System.out.println("inputStream1: " + line);
                  str_inputStream += line + System.getProperty("line.separator");
            }

            // Capture any process output
            br = new BufferedReader(new InputStreamReader(pExecution.getInputStream()));
            line = "";
            str_inputStream = "";
            while ((line = br.readLine()) != null && br.ready()) {
                  System.out.println("inputStream2: " + line);
                  str_inputStream += line + System.getProperty("line.separator");
            }

                Integer iExitVal = pExecution.waitFor();

The funny thing is that my first ftp script uses Windows ftp and logs into an AIX server and uses DIR to list 2 files.  If I use at least 3 Input Streams I can get everything into str_inputStream and the process finishes.  The other script I call uses putty's psftp program and seems to only use 1 input stream, but ends up hanging on the second file I try to "ls".

Could this have something to do with InputStream buffer sizes?  Is there a way to do this without limits to the size?

Thanks,
Courtenay

Avatar of Mick Barry
Mick Barry
Flag of Australia image

you should only have one loop to read the output
and get rid of the br.ready() call from the loop condition

http://helpdesk.objects.com.au/java/runtime-exec-locks-up

worth also checking that the process isn't writing to stderr as well
Avatar of courtenayt
courtenayt

ASKER

Thanks for your help!  I'm not sure if I can use the separate thread approach, since I need to be able to get the str_inputStream and str_errorStream from the class that calls an instance of the class containing  executeCmd(String sCommand).  

Here is what I have so far, when it executes it runs through the 1st while loop 2 times and hangs on evaluating the while condition the third time.


      public Integer executeCmd(String sCommand) throws IOException, InterruptedException{
            Runtime rShell = Runtime.getRuntime();
            Process pExecution = rShell.exec(sCommand);
            
            String line = null;
            str_inputStream = "";
            str_errorStream = "";
            
            // Capture any process output
            BufferedReader br1 = new BufferedReader(new InputStreamReader(pExecution.getInputStream()));
            while ((line = br1.readLine()) != null) {
                  System.out.println("inputStream1: " + line);
                  str_inputStream += line + System.getProperty("line.separator");
            }
            
            // Capture any process errors
            line = null;
            BufferedReader br2 = new BufferedReader(new InputStreamReader(pExecution.getErrorStream()));
            while ((line = br2.readLine()) != null) {
                  System.out.println("errorStream1: " + line);
                  str_errorStream += line + System.getProperty("line.separator");
            }
                        
            Integer iExitVal = pExecution.waitFor();
            return iExitVal;
      }
are you sure thats where it is hanging?
When I use the debugger that is where it sits for ages unless i manually terminate it
ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I tried the following to call the StreamGobbler running the same script:

      public static Integer execute(String sCommand) throws InterruptedIOException
      {
            Integer iExitVal = 0;
            
            try
            {
                  Runtime rShell = Runtime.getRuntime();
                  Process pExecution = rShell.exec(sCommand);
                  // Capture any process errors
                  StreamGobbler sgError = new StreamGobbler(pExecution.getErrorStream(), "APP");
                  // Capture any process output
                  StreamGobbler sgOutput = new StreamGobbler(pExecution.getInputStream(), "OUTPUT");
                  sgError.start();
                  sgOutput.start();
                  
                  iExitVal = pExecution.waitFor();
                  
                  System.out.println("Exit value: " + iExitVal);
            }
            catch (Exception ex)
            {
                  throw new InterruptedIOException(":CommandRunner: " + ex.getMessage());
            }
            
            return iExitVal;
      }



And now it freezes here: iExitVal = pExecution.waitFor();

I know the script works and quits out of the ftp because it works on the commandline to call it, and the weirdest thing is it sometimes works when I run it my old way & sometimes not.  Makes me think it has to do with a buffer size, or something weird.  

Also I do need a way to get the output in the calling class, so I'm not sure, even if this worked, if it would meet my needs to have it execute in a separate thread.
what is the value of sCommand?
Woops - I take that back.  It is working with the StreamGobbler, forgot to change a setting.

Is there a good way I can adapt this so I can get a String with the output and a String with the errors into the class that calls the execute(String sCommand) method I posted above?

Thanks,
Courtenay
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks so much this solved the problem!