2009-09-22 39 views
1

我有一个使用curl命令从FTP服务器下载3个文件的脚本(准确的说是KSH脚本)。从java程序运行bash脚本时出现奇怪的行为

当我手动运行我的脚本,即通过执行命令./ftp_download.sh XXX(XXX是脚本的参数),下载完成正确。

,因为我想从运行Java程序的脚本,我已经完全包含一个简短的Java类:

public class Run { 

    private static final String CMD = "/.../sh/ftp_download.sh XXX"; 

    public static void main(String[] args) { 
     System.out.println("========================================================"); 
     BufferedReader out = null; 
     try { 
      long startTime = System.currentTimeMillis(); 
      String strOutputline; 
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
      Date now = new Date(); 
      Process processus = Runtime.getRuntime().exec(CMD); 
      out = new BufferedReader(new InputStreamReader(processus.getInputStream())); 
      while ((strOutputline = out.readLine()) != null) { 
       now.setTime(System.currentTimeMillis()); 
       System.out.println(sdf.format(now) + " " + strOutputline); 
      } 
      System.out.println("RESULT : " + processus.waitFor()); 
      out.close(); 
      processus.destroy(); 
      long duration = System.currentTimeMillis() - startTime; 
      System.out.println("Duration : " + duration); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       if (out != null) { 
        out.close(); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     System.out.println("========================================================"); 
     System.out.println("END"); 
    } 

} 

然而,当我运行这个简单的程序,它只是正好3m20后冻结(这个持续时间总是相同的,即使我多次运行Java程序)。我的意思是Java程序仍在运行(curl过程),但下载的文件不再增长(即curl不会继续下载任何数据)...

因此,我从来没有得到RESULT: xxx行打印在控制台上...

什么能解释这种奇怪的行为?

PS:在不远的将来,我会改变我的项目,以便使用Apache公地网库下载这些文件,但我真的想了解这种奇怪的行为!


由于derobert,我终于设法解决这个问题。一些解释:在正常模式下,curl正在显示一个进度信息(一个表格包含下载的数据量,剩余时间等)。过了一段时间,缓冲区似乎完全填满了,这就是为什么这个过程冻结的原因...

+0

你可以尝试strace在java进程,看看它的等待/挂起。 – vpram86 2009-09-22 14:08:56

+0

伙计,从java程序运行bash脚本* IS *一个奇怪的行为:)抱歉,无法抗拒... – 2009-09-22 14:29:47

回答

13

我不是一个Java人,而是一个Unix的人,而且有一点似乎很明显:stdout上的缓冲区或者stderr正在填满,然后卷曲被阻挡。

如果您在无声模式下运行卷曲,如curl --silent那样工作吗?

检查Java文档,它看起来像除了getInputStream之外还想使用getErrorStream

+0

我已经通知,如果我不使用“-v”(详细)属性,我赢了过程冻结前20秒。我会尝试使用“-s”(无声)选项... – romaintaz 2009-09-22 14:14:03

+0

+1对于优秀的诊断 – janko 2009-09-22 14:17:28

+0

无声模式解决了我的问题!非常感谢... – romaintaz 2009-09-22 14:26:30

1

Process

父进程使用这些流喂输入和从子得到输出。由于某些本地平台仅为标准输入和输出流提供有限的缓冲区大小,因此无法及时写入输入流或读取子流程的输出流可能会导致子流程阻塞甚至死锁。

所以,你需要得到standard output和过程的error output和阅读他们,直到他们是空的(即返回-1read())。