Java - 运行 子进程在本地工作,但在 Heroku 上 运行 时失败并显示 "broken pipe"?

Java - Running a subprocess works locally but fails with "broken pipe" when ran on Heroku?

作为背景,我有一个基于 Java 的 Discord 机器人部署在 Heroku 上,使用 1 个免费的 worker dyno。我需要 运行 一个 .exe 文件(stockfish 12 可执行文件),将输入传递给它并处理它的输出。我正在使用 Java RunTime 来创建此进程,但是当我尝试使用 flush() 方法向其发送输入时,会抛出 broken pipe 错误。我假设 Heroku 必须以某种方式关闭输入/输出流,因为这段代码 运行 在本地没问题。 Heroku 对创建子进程有限制吗?

app[worker.1]: chess.player.ai.stockfish.exception.StockfishEngineException: java.io.IOException: 管道损坏 app[worker.1]: 在 chess.player.ai.stockfish.engine.UCIEngine.sendCommand(UCIEngine.java:39) app[worker.1]: 在 chess.player.ai.stockfish.engine.UCIEngine.passOption(UCIEngine.java:77) app[worker.1]: 在 chess.player.ai.stockfish.engine.UCIEngine.(UCIEngine.java:23) app[worker.1]: 在 chess.player.ai.stockfish.engine.Stockfish.(Stockfish.java:13) app[worker.1]: 在 chess.player.ai.stockfish.StockFishClient.(StockFishClient.java:21) app[worker.1]:在 chess.player.ai.stockfish.StockFishClient$Builder.build(StockFishClient.java:80)

编辑:我试图通过对单个命令进行硬编码来简化程序,但它仍然无法通过 writer.flush() 行。没有打印任何内容。

Process process = new ProcessBuilder().command("bin/stockfish_20090216_x64_bmi2.exe").start();

StringBuilder output = new StringBuilder();
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
writer.write("position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" + "\n");
writer.write("go movetime 1000");
writer.flush();

String line;
while ((line = input.readLine()) != null) {
    output.append(line + "\n");
}

int exitVal = process.waitFor();
if (exitVal == 0) {
    System.out.println("success");
    System.out.println(output.toString());
}
else {
    System.out.println("error");
}

output 流自行关闭。当您 运行 命令时,创建一个新进程或此命令必须阻塞流并等待输入。

推荐ProcessBuilder,配置更方便:

new ProcessBuilder().command("cmd.exe", "/c", "command")
                    .directory(new File(path))
                    .redirectInput(new File(path, "input.txt"))
                    .redirectOutput(new File(path, "output.txt"))
                    .redirectError(new File(path, "runtime_error.txt"))
                    .start()
                    .waitFor();

原来我使用了错误的二进制文件。 Stockfish 二进制文件有许多不同的格式,显然适用于我的本地文件的格式不适用于 Heroku。