我有一个脚本(准确地说是KSH脚本),它使用curl
命令从FTP服务器下载3个文件。
当我手动运行我的脚本时,即执行命令./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 commons-net库下载这些文件,但我真的想要了解这种奇怪的行为!
感谢 derobert ,我终于设法解决了这个问题。一些解释:在正常模式下,curl
显示进度信息(包含下载数据量的表,剩余时间等)。一段时间后,缓冲区似乎完全填满了,这就是为什么这个过程冻结了......
答案 0 :(得分:13)
我不是Java用户,而是Unix用户,有一点似乎很明显:stdout或stderr上的缓冲区正在填满,然后curl阻塞。
如果您在静默模式下运行curl,它是否有效,如curl --silent
?
检查Java文档,除了getInputStream之外,您似乎还想使用getErrorStream
。
答案 1 :(得分:1)
来自Process:
父进程使用这些流向子进程提供输入并从子进程获取输出。由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此无法及时写入输入流或读取子进程的输出流可能导致子进程阻塞,甚至死锁。
因此,您需要获取流程的standard output和error output并阅读它们,直到它们为空(即在read()上返回-1
)。