【问题标题】:Java - How do I detect if bash has returned?Java - 如何检测 bash 是否返回?
【发布时间】:2016-02-14 01:09:51
【问题描述】:

我正在编写一个程序,我想在后台启动一个 shell,并发送和接收输入和输出。我已经设法做到这一点,并且可以成功地读写这个过程。这就是我遇到麻烦的地方。

我想在ShellManager(见下面的代码)中有一个方法,它会一直等到进程完成/失败,然后将输入返回给用户。

例如,如果我发送tar xzf something_that_will_take_a_while.tar.gz, 我可以在输出中看到它是如何花费时间的,然后回显:

]0;~
[32mMe@MyComputer [33m~[0m

我已经尝试阻塞线程直到收到]0;~,但这不起作用。 (从未返回)

我也试过\u001B,同样的问题:(

我不确定符号是什么,也找不到太多关于如何检测进程何时返回的信息。

这是我的代码:

package buildSystem.shell;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import base.TermConstants;

public class ShellManager {
    private InputStream termOut;
    private OutputStream termIn;

    private ProcessBuilder build;
    private Process main;

    BufferedReader reader;
    BufferedWriter writer;

    public ShellManager() {
        build = new ProcessBuilder(TermConstants.getShellLocation());
        build.redirectErrorStream(true);    
    }

    public void start() throws IOException {
        try {
            main = build.start();
            termOut = main.getInputStream();
            termIn = main.getOutputStream();
            reader = new BufferedReader (new InputStreamReader(termOut));
            writer = new BufferedWriter(new OutputStreamWriter(termIn));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void writeLine(String s) throws IOException {
        writer.write(s);
        writer.newLine();
        writer.flush();
    }

    public String readNextLine() throws IOException {
        return reader.readLine();
    }

    public void end() {
        try {
            writeLine("exit\n");
            main.waitFor();
            termOut.close();
            termIn.close();
            reader.close();
            writer.close();
        } catch (IOException | InterruptedException e) {
            kill();
        }
    }

    public void kill() {
        main.destroyForcibly();
        try {
            termOut.close();
            termIn.close();
            reader.close();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

/*THE PART I AM HAVING TROUBLE WITH:*/

    public void waitForReturn() {
        try {
            while(reader.readLine() != "\u001B") {}
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

基本上,我想要一种可靠的方法来检测程序何时从 bash shell 退出。 bash 进程仍将运行,但从该 bash 实例运行的程序将返回。因此我不能使用process.waitFor()

我尝试等待]0;~,然后等待[32mMe@MyComputer [33m~[0m,直到 tar 退出并出现错误代码,在这种情况下,这两行将被颠倒。我不确定如何继续,因为检测 bash 已返回给用户应该是一项相对容易的任务。

感谢您的帮助!

【问题讨论】:

  • 您必须在调用waitFor() 之前关闭流。否则你就会陷入僵局。

标签: java linux bash shell process


【解决方案1】:

如果这代表您尝试匹配输出的方式,那就是您的问题:

while(reader.readLine() != "\u001B") {}

除特殊情况外,您必须在String 实例上使用equals() 方法:

while (true) {
  String line = reader.readLine();
  if ((line == null) || "\u001B".equals(line))
    break;
}

我不知道你为什么在进程退出时期望ESC 和换行符。

【讨论】:

  • 那行得通。老实说,我不知道为什么我没有看到这一点,因为我通常不会犯那个错误。非常感谢!另外,我正在检查esc,只是因为我已经尝试了我能想到的所有其他方法。我完全错过了实际的探测,所以再次感谢你找到它。我仍然无法相信这是这么简单的事情。
【解决方案2】:

我相信你需要调用 Process.waitFor() 方法。 所以你需要这样的东西:

Process p = build.start();
p.waitFor()

如果您尝试模拟 bash shell,允许输入命令、执行和处理输出而不终止。有一个开源项目可能是有关如何执行此操作的代码的一个很好的参考。它在 Git 上可用。看看Jediterm Pure Java Emulator。

考虑模拟 bash,我还发现 Piping between processes 的这个示例也很相关。

它确实展示了如何提取执行进程的输出并将该数据作为输入传输到另一个 Java 进程。应该会有所帮助。

【讨论】:

  • 您好,感谢您的回复!不幸的是,这不起作用,因为当 bash 运行时,进程正在运行,即使它已经返回给用户。但是,如果 shell 在运行命令后退出,这将起作用,但这不是我需要的。无论如何感谢您的回复!
  • @TooManyPolygons 您的问题是如何判断 bash 何时返回。如果这不是您真正的意思,请解决您的问题。
  • @erickson 我不确定你的意思。它用 bold 字母明确指出我不能使用process.waitFor()。 (不是在发布答案时,而是在您发表评论之前)。为什么我的问题需要“修复”?这是非常具体的。我不明白为什么在我回复答案并告诉我需要修改后 2 个月出现是有帮助的。所以不行。我的问题不是“你怎么知道 bash 什么时候回来了”,它更具体。如果您不喜欢它,请至少尝试并说明原因。你真的读了吗?
  • 在我发布关于 waitfor() 的回答后,您更新了问题; ;)
  • @pczeus 是的,我做到了 :) 我很感激你的回答,即使它不是我所需要的。
猜你喜欢
  • 2010-10-29
  • 1970-01-01
  • 1970-01-01
  • 2017-08-21
  • 2016-12-29
  • 2023-03-05
  • 2021-05-28
  • 1970-01-01
相关资源
最近更新 更多