从 java 程序运行 bash 脚本时的奇怪行为

发布于 2024-08-05 15:45:16 字数 2217 浏览 4 评论 0原文

我有一个脚本(准确地说是 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");
    }

}

但是,当我运行这个简单的程序时,它会在 3 分 20 秒后冻结(这个持续时间始终相同,即使我多次运行 Java 程序)。 我所说的冻结是指 Java 程序仍在运行(curl 进程也是如此),但下载的文件不再增长(即 curl 不再继续下载任何数据) )...

因此,我从未在控制台中打印 RESULT: xxx 行...

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

ps:在不久的将来,我将更改我的项目以便使用 Apache commons-net 库下载这些文件,但我真的想了解这种奇怪的行为!


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

I have a script (KSH script to be precise) that downloads 3 files from a FTP server, using the curl command.

When I run manually my script, i.e. by executing the command ./ftp_download.sh XXX (XXX are the parameters for the script), the download finishes correctly.

As I want to run the script from a Java program, I have made a short Java class that contains exactly that:

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");
    }

}

However, when I run this simple program, it simply freezes after exactly 3m20 (this duration is always the same, even if I run the Java program several times).
By freezing, I mean that the Java program is still running (the curl process too) but the downloaded file is not growing anymore (i.e. curl does not continue to download any data)...

Thus, I never get the RESULT: xxx line printed in the console...

What can explain this strange behavior?

ps: In the near future, I will change my project in order to download these files using the Apache commons-net library, but I really want to understand this strange behavior!


Thanks to derobert, I finally manage to solve this issue. Some explanations: in normal mode, curl is displaying a progress information (a table with the amount of data downloaded, the remaining time, etc.). After some time, the buffer seems to be completly filled, and that's why the process freezes...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

離殇 2024-08-12 15:45:16

我不是 Java 人,而是 Unix 人,有一件事情似乎很明显:stdout 或 stderr 上的缓冲区已满,然后curl 阻塞。

如果您在静默模式下运行curl(如curl --silent),它会起作用吗?

检查Java文档,看起来您还想使用 getErrorStream

I'm not a Java person, but rather a Unix one, and one thing seems obvious: The buffer on either stdout or stderr is filling up, and then curl is blocking.

Does it work if you run curl in silent mode, as in curl --silent?

Checking the Java documentation, it looks like you want to also use getErrorStream in addition to getInputStream.

爱给你人给你 2024-08-12 15:45:16

来自 进程

父进程使用这些流向子进程提供输入并从子进程获取输出。由于某些原生平台只为标准输入输出流提供有限的缓冲区大小,因此未能及时写入子进程的输入流或读取子进程的输出流可能会导致子进程阻塞,甚至死锁。

因此,您需要获取 标准输出错误输出进程并读取它们直到它们为空(即在 read())。

From Process:

The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

So you need to get the standard output and the error output of the process and read them until they’re empty (i.e. returning -1 on read()).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文