Java - 如何检测 bash 是否已返回?

Java - How do I detect if bash has returned?

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

我想在 ShellManager 中有一个方法(见下面的代码)等待直到进程正在做的任何事情 finishes/fails,并且 returns 向用户输入。

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

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

我已经尝试阻塞线程直到收到 ]0;~,但没有成功。 (从未返回)

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

我不确定符号是什么,也找不到很多关于如何检测进程何时 returns。

这是我的代码:

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 进程仍将 运行ning,但来自 bash 实例的程序 运行ning 将返回。因此我不能使用 process.waitFor().

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

感谢您的帮助!

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

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

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

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

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

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

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

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

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

我不确定你为什么期望 ESC 和进程退出时换行。