2009-09-21 5 views
9

Wenn ich Ant über die Befehlszeile ausführen, bekomme ich einen Nicht-Null-Beendigungsstatus ($? Unter UNIX,% ERRORLEVEL% unter Windows). Aber wir haben ein Java-Programm, das läuft (über ProcessBuilder), und wenn Ameisen scheitert, können wir unter Windows den Exit-Status nicht bekommen.Warum gibt ant.bat bei der programmgesteuerten Ausführung keinen Fehlerstatus zurück?

Ich überprüfte dies nur mit dieser einfachen ant Testdatei:

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

Unter UNIX läuft ant druckt eine Fehlermeldung, und Echo $? danach druckt 1. Unter Windows Ameise läuft oder ant.bat druckt eine Fehlermeldung, und% Error-% Echo später druckt 1.

nun unter dem Testprogramm: Unter UNIX Java ant druckt einen Fehler Nachricht und echo $? nachher druckt 1. Unter Windows kann java Run amt kein Programm mit dem Namen ant zum Ausführen finden, aber java Run ant.bat gibt eine Fehlermeldung aus, aber echo% ERRORLEVEL% druckt danach . Was gibt?

Wir verlassen uns darauf, den Exit-Status nach der Ausführung von ant überprüfen zu können. Wir waren sowieso. Warum können wir uns nicht programmatisch darauf verlassen?

Testprogramm:

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

Antwort

1

Müssen Sie Ant über seine .bat-Datei ausführen? Es ist nur ein Java-Programm, das Sie einfach innerhalb der VM ausführen können, indem Sie die Ant-Laufzeit direkt instanziieren und ausführen. Schauen Sie in ant.bat nach, sehen Sie, was seine Hauptklasse ist, und führen Sie sie direkt aus.

+0

ant.bat ist komplex und läuft das Java-Programm direkt ist entsprechend komplex. Ich sehe das gleiche Problem bei der Ausführung von ant.bat innerhalb eines ant-Skripts (nein, frag nicht). Ich kann den ant.bat errorlevel nicht sehen. Ich möchte ant2.bat nicht in die Umgebung meines Herstellers liefern, aber ich werde es tun, wenn ich muss. Weiß jemand * warum * das funktioniert? PS: Was ist die Formatierung Markup für diesen Kommentar ??? –

0

Dies ist ein seit langem bestehendes Problem für ältere Versionen von Ant unter Windows. Ich glaube, es wurde in Version 1.7.0 behoben.

Details siehe this bug und this discussion für einen Ansatz, um es zu adressieren.

+1

Ich bin auf der Ameise 1.7.1. Ich habe gerade versucht, mit dem vollständigen Pfad zu laufen, um sicherzustellen, dass ich keine andere Version von ant laufen habe. Gleiches Verhalten: Korrekte Fehlerstufe bei Ausführung von einer Eingabeaufforderung; falscher Fehlerlevel, wenn er von einem Programm ausgeführt wird. – skiphoppy

2

löste ich dieses Problem, indem zwei zusätzliche Batch-Dateien erstellen (nicht sehr schön, aber es funktioniert):

Inhalt der Datei myant.bat:

call ant2.bat %* 

Inhalt der Datei ant2.bat:

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

Jetzt kann ich myant.bat als Process von Java anrufen und ich bekomme den richtigen Ausgangswert.

Sorry, ich kann nicht sagen warum dies funktioniert. Es ist einfach das Ergebnis von vielen Versuchen.

0

Ich googelte zu diesem Thread und finde tangens 'Antwort fast mein Problem gelöst: die Exit codiert sind immer 0 auf Windows von ant.bat, auch wenn ich absichtlich einen Ameisenbau fehlgeschlagen; Ich muss den Exit-Code von einem TFS-Build-Skript abrufen, und es zeigte, dass auch die %ERRORLEVEL% nicht in TFS-Build gefunden werden kann.

Allerdings muss ich die /B von exit Zeilen entfernen, sonst zeigt es immer noch mir Exit Code 0.

6

löste ich dieses Problem durch eine einzelne Batch-Datei erstellen (ziemlich viel schöner als die oben aber immer noch geheimnisvoll):

Inhalt der Datei myant.bat:

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

entscheidend, ohne Code was auch immer nach dem call.

+0

+1 Hatte das gleiche Problem versuchen, ant von psake anzurufen. Das hat mein Problem behoben. –

2

Eine schnelle Patch nach dem am Ende der ANT.BAT Datei hinzufügen:

exit /b %ANT_ERROR% 

Dieses Problem vor kurzem hat lange existiert und fixiert. Siehe Bug 41039.

Es sollte in ANT Release 1.8.2 oder höher bereit sein.

2

Ein weiteres Problem - wenn Sie ANT innerhalb einer BAT-Datei aufrufen und daran interessiert sind, den errorlevel-Wert zu speichern, müssen Sie den Aufruf aus einem if/else-Block heraushalten.

Zum Beispiel wird dies nicht funktionieren (... in der Mitte einige Routine):

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

Sie müssen den Anruf auszubrechen als (... außerhalb dieser Routine gesetzt) ​​folgt:

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

(... in der Mitte einiger Routinen)

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

i IF ERRORLEVEL 1 mit 01 ersetzen ausgewertete:

call ant 

IF %ERRORLEVEL% NEQ 0 GOTO :build_error