• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 779
  • Last Modified:

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

0
courtenayt
Asked:
courtenayt
  • 5
  • 5
2 Solutions
 
objectsCommented:
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
0
 
courtenaytAuthor Commented:
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;
      }
0
 
objectsCommented:
are you sure thats where it is hanging?
0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
courtenaytAuthor Commented:
When I use the debugger that is where it sits for ages unless i manually terminate it
0
 
objectsCommented:
try using the class in the link I posted above to handle the stream reading from a different thread
0
 
courtenaytAuthor Commented:
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.
0
 
objectsCommented:
what is the value of sCommand?
0
 
courtenaytAuthor Commented:
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
0
 
objectsCommented:
store the returned string as a member var of the StreamGobbler class, and add a method that returns it. You can then call it to get the string when waitFor() is done

0
 
courtenaytAuthor Commented:
Thanks so much this solved the problem!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 5
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now