为什么 ant.bat 在以编程方式运行时不返回错误状态?

发布于 2024-08-05 04:38:46 字数 1998 浏览 2 评论 0原文

当我从命令行运行 ant 时,如果出现故障,我会得到非零退出状态(UNIX 上为 $?,Windows 上为 %ERRORLEVEL%)。但是我们有一个运行 ant 的 Java 程序(通过 ProcessBuilder),当 ant 失败时,在 Windows 上我们无法获得退出状态。

我刚刚用这个简单的 ant 测试文件验证了这一点:

<project name="x" default="a">
  <target name="a">
    <fail/>
  </target>
</project>

在 UNIX 上,运行 ant 会打印一条失败消息,并回显 $?然后打印 1。 在 Windows 上,运行 ant 或 ant.bat 会打印一条失败消息,然后回显 %ERRORLEVEL%,然后打印 1。

现在,使用下面的测试程序: 在 UNIX 上,java Run ant 打印一条失败消息,并回显 $?然后打印 1。 在 Windows 上,java Run ant 找不到要运行的名为 ant 的程序,但 java Run ant.bat 打印一条失败消息,但随后回显 %ERRORLEVEL% 并打印 0。什么给?

我们依赖于运行 ant 后能够检查退出状态。无论如何,我们是。为什么我们不能以编程方式依赖它?

测试程序:

import java.io.*;

public class Run {
  public static void main(String[] args) throws IOException, InterruptedException {
    ProcessBuilder pb = new ProcessBuilder(args);
    Process p = pb.start();
    ProcThread stdout = new ProcThread(p.getInputStream(), System.out);
    ProcThread stderr = new ProcThread(p.getErrorStream(), System.err);
    stdout.start();
    stderr.start();
    int errorLevel = p.waitFor();
    stdout.join();
    stderr.join();
    IOException outE = stdout.getException();
    if (outE != null)
      throw(outE);
    IOException errE = stdout.getException();
    if (errE != null)
      throw(errE);
    System.exit(errorLevel);
  }

  static class ProcThread extends Thread {
    BufferedReader input;
    PrintStream out;
    IOException ex;

    ProcThread(InputStream is, PrintStream out) {
      input = new BufferedReader(new InputStreamReader(is));
      this.out = out;
    }

    @Override
    public void run() {
      String line;
      try {
        while ((line = input.readLine()) != null)
          out.println(line);
      } catch (IOException e) {
        setException(e);
      }
    }

    private void setException(IOException e) {
      this.ex = e;
    }

    public IOException getException() {
      return ex;
    }
  }
}

When I run ant from the command-line, if I get a failure, I get a non-zero exit status ($? on UNIX, %ERRORLEVEL% on Windows). But we have a Java program which is running ant (through ProcessBuilder), and when ant fails, on Windows we cannot get the exit status.

I just verified this with this simple ant test file:

<project name="x" default="a">
  <target name="a">
    <fail/>
  </target>
</project>

On UNIX, running ant prints a failure message, and echoing $? afterward prints 1.
On Windows, running ant or ant.bat prints a failure message, and echoing %ERRORLEVEL% afterward prints 1.

Now, using the test program below:
On UNIX, java Run ant prints a failure message, and echoing $? afterward prints 1.
On Windows, java Run ant can't find a program named ant to run, but java Run ant.bat prints a failure message, yet echoing %ERRORLEVEL% afterward prints 0. What gives?

We're relying on being able to check the exit status after running ant. We were, anyway. Why can't we rely on this, programmatically?

Test program:

import java.io.*;

public class Run {
  public static void main(String[] args) throws IOException, InterruptedException {
    ProcessBuilder pb = new ProcessBuilder(args);
    Process p = pb.start();
    ProcThread stdout = new ProcThread(p.getInputStream(), System.out);
    ProcThread stderr = new ProcThread(p.getErrorStream(), System.err);
    stdout.start();
    stderr.start();
    int errorLevel = p.waitFor();
    stdout.join();
    stderr.join();
    IOException outE = stdout.getException();
    if (outE != null)
      throw(outE);
    IOException errE = stdout.getException();
    if (errE != null)
      throw(errE);
    System.exit(errorLevel);
  }

  static class ProcThread extends Thread {
    BufferedReader input;
    PrintStream out;
    IOException ex;

    ProcThread(InputStream is, PrintStream out) {
      input = new BufferedReader(new InputStreamReader(is));
      this.out = out;
    }

    @Override
    public void run() {
      String line;
      try {
        while ((line = input.readLine()) != null)
          out.println(line);
      } catch (IOException e) {
        setException(e);
      }
    }

    private void setException(IOException e) {
      this.ex = e;
    }

    public IOException getException() {
      return ex;
    }
  }
}

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

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

发布评论

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

评论(8

三生池水覆流年 2024-08-12 04:38:47

我通过创建一个单个批处理文件解决了这个问题(比上面的好一点,但仍然很神秘):

文件myant.bat的内容:

@echo off
rem RunAnt simply calls ant -- correctly returns errorlevel for callers
call ant.bat %*

至关重要的是,没有任何代码在通话之后。

I solved this problem by creating a single batch file (quite a bit nicer than the above but still mysterious):

Content of file myant.bat:

@echo off
rem RunAnt simply calls ant -- correctly returns errorlevel for callers
call ant.bat %*

crucially, without any code whatsoever after the call.

君勿笑 2024-08-12 04:38:47

我通过创建两个额外的批处理文件解决了这个问题(不是很好,但它有效):

文件 myant.bat 的内容:

call ant2.bat %*

文件 ant2.bat 的内容:

call ant.bat %*
if errorlevel 1 (goto ERROR_EXIT)
exit /B 0
:ERROR_EXIT
exit /B 1

现在我可以从java调用myant.bat作为Process,并且我得到了正确的退出值。

抱歉,我无法说出为什么这有效。这只是多次尝试的结果。

I solved this problem by creating two extra batch files (not very nice, but it works):

Content of file myant.bat:

call ant2.bat %*

Content of file ant2.bat:

call ant.bat %*
if errorlevel 1 (goto ERROR_EXIT)
exit /B 0
:ERROR_EXIT
exit /B 1

Now I can call myant.bat as a Process from java and I get the correct exit value.

Sorry, I cannot say why this works. It's simply the result of a many many tries.

固执像三岁 2024-08-12 04:38:47

一个快速补丁是在 ANT.BAT 文件末尾添加以下内容:

exit /b %ANT_ERROR%

这个问题长期以来一直存在,最近已修复。请参阅错误 41039

它应该在 ANT 版本 1.8.2 或更高版本中准备就绪。

A quick patch is adding the following at the end of ANT.BAT file:

exit /b %ANT_ERROR%

This problem has long existed and fixed recently. Refer to Bug 41039.

It should be ready in ANT release 1.8.2 or later.

短叹 2024-08-12 04:38:47

另一个问题 - 如果您在 BAT 文件中调用 ANT 并且您有兴趣保存错误级别值,则必须将调用保留在 if/else 块之外。

例如,这不起作用(...在某个例程的中间):

if "%DUMP_ARGS%"=="no" (
   call ant %ANT_TARGETS%
   set ANT_RETURN=%errorlevel%
)

您必须按如下方式中断调用(...放置在该例程之外):

:call_ant
call ant %ANT_TARGETS%
set ANT_RETURN=%errorlevel%
goto :eof

(...在某个例程的中间)

if "%DUMP_ARGS%"=="no" (
    call :call_ant
)

Another issue - if you call ANT within a BAT file and you are interested in saving the errorlevel value, you must keep the call out of an if/else block.

For example, this won't work (...in the middle of some routine):

if "%DUMP_ARGS%"=="no" (
   call ant %ANT_TARGETS%
   set ANT_RETURN=%errorlevel%
)

You must break out the call as follows (...placed outside that routine):

:call_ant
call ant %ANT_TARGETS%
set ANT_RETURN=%errorlevel%
goto :eof

(...in the middle of some routine)

if "%DUMP_ARGS%"=="no" (
    call :call_ant
)
看海 2024-08-12 04:38:47

您需要通过 Ant 的 .bat 文件运行它吗?它只是一个java程序,您可以通过直接实例化并执行Ant运行时来在VM内部执行。看一下ant.bat里面,看看它的Main类是什么,直接执行。

Do you need to run Ant via its .bat file? It's just a java program, you could just execute in inside the VM by directly instantiating and executing the Ant runtime. Have a look inside ant.bat, see what its Main class is, and execute it directly.

我很OK 2024-08-12 04:38:47

对于 Windows 上旧版本的 Ant 来说,这是一个长期存在的问题。我相信它已在 1.7.0 版本中修复。

请参阅此错误了解详细信息和此讨论以获取解决该问题的方法。

This is a long-standing issue for older versions of Ant on Windows. I believe it has been fixed in version 1.7.0.

See this bug for details and this discussion for an approach to address it.

情话已封尘 2024-08-12 04:38:47

我用谷歌搜索到这个帖子,发现 tangens 的答案几乎解决了我的问题:在 Windows 上,来自 ant.bat 的退出编码始终为 0,即使我故意使 ant 构建失败;我需要从 TFS 构建脚本获取退出代码,它表明甚至在 TFS 构建中也找不到 %ERRORLEVEL%

但是,我必须从 exit 行中删除 /B ,否则,它仍然总是显示退出代码 0。

I googled to this thread and find tangens' answer almost solved my problem: the exit coded are always 0 on Windows from ant.bat, even when I intentionally failed an ant build; I need to get the exit code from a TFS build script, and it showed that even the %ERRORLEVEL% can't be found in TFS build.

However, I have to remove the /B from exit lines, otherwise, it still always shows me exit code 0.

请别遗忘我 2024-08-12 04:38:47

我解决了用 IF %ERRORLEVEL% NEQ 0 替换 IF ERRORLEVEL 1 的问题:

call ant

IF %ERRORLEVEL% NEQ 0 GOTO :build_error

i solved replacing IF ERRORLEVEL 1 with IF %ERRORLEVEL% NEQ 0:

call ant

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