2009-09-21 39 views
9

Khi tôi chạy kiến ​​từ dòng lệnh, nếu tôi gặp lỗi, tôi nhận được trạng thái thoát khác không ($? Trên UNIX,% ERRORLEVEL% trên Windows). Nhưng chúng ta có một chương trình Java đang chạy ant (thông qua ProcessBuilder), và khi ant không thành công, trên Windows chúng ta không thể có được trạng thái thoát.Tại sao ant.bat không trả lại trạng thái lỗi khi chạy theo chương trình?

Tôi chỉ xác nhận điều này với đơn giản tập tin này ant test:

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

Trên UNIX, chạy in ant một thông báo lỗi, và lặp lại $? sau đó in 1. Trên Windows, chạy kiến ​​hoặc ant.bat in thông báo lỗi và lặp lại% ERRORLEVEL% sau đó in 1.

Bây giờ, sử dụng chương trình thử nghiệm dưới đây: Trên UNIX, java Chạy ant in a failure và nhắn lại $? sau đó in 1. Trên Windows, java Chạy kiến ​​không thể tìm thấy một chương trình có tên là ant để chạy, nhưng java Chạy ant.bat in một thông báo lỗi, nhưng lặp lại% ERRORLEVEL% sau đó in . Đưa cái gì?

Chúng tôi đang dựa vào việc có thể kiểm tra trạng thái thoát sau khi chạy ant. Dù sao thì chúng tôi cũng vậy. Tại sao chúng ta không thể dựa vào điều này, lập trình?

chương trình thử nghiệm:

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

Trả lời

1

Bạn cần phải chạy Ant qua tập tin .bat của nó? Nó chỉ là một chương trình java, bạn chỉ có thể thực thi bên trong máy ảo bằng cách trực tiếp khởi tạo và thực hiện thời gian chạy Ant. Có một cái nhìn bên trong ant.bat, xem lớp Main của nó là gì và thực thi nó trực tiếp.

+0

ant.bat là phức tạp và chạy chương trình java trực tiếp tương ứng phức tạp. Tôi thấy cùng một vấn đề thực thi ant.bat từ bên trong một kịch bản kiến ​​(không, đừng hỏi). Tôi không thể nhìn thấy lỗi ant.bat. Tôi không muốn cung cấp ant2.bat cho môi trường của nhà xây dựng, nhưng tôi sẽ phải làm thế. Có ai biết * tại sao * tính năng này hoạt động không? PS: Đánh dấu định dạng cho nhận xét này là gì ??? –

0

Đây là sự cố lâu dài đối với các phiên bản Ant cũ hơn trên Windows. Tôi tin rằng nó đã được sửa trong phiên bản 1.7.0.

Xem this bug để biết chi tiết và this discussion để biết cách tiếp cận.

+1

Tôi đang ở phiên bản 1.7.1. Tôi chỉ cố gắng chạy với con đường đầy đủ để đảm bảo rằng tôi không chạy một phiên bản kiến ​​khác. Hành vi tương tự: mức lỗi chính xác khi chạy từ lời nhắc; errorlevel không chính xác khi chạy từ một chương trình. – skiphoppy

2

tôi giải quyết vấn đề này bằng cách tạo ra hai tập tin batch thêm (không phải là rất tốt đẹp, nhưng nó hoạt động):

Nội dung của tập tin myant.bat:

call ant2.bat %* 

Nội dung của tập tin ant2.bat:

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

Bây giờ tôi có thể gọi myant.bat làm số Process từ java và tôi nhận được giá trị thoát đúng.

Rất tiếc, tôi không thể nói lý do tại sao hoạt động. Nó đơn giản là kết quả của rất nhiều lần thử.

0

Tôi googled vào chủ đề này và tìm thấy câu trả lời của tangens gần như giải quyết vấn đề của tôi: lối ra được mã hóa luôn luôn là 0 trên Windows từ ant.bat, ngay cả khi tôi cố tình thất bại một kiến ​​xây dựng; Tôi cần lấy mã thoát từ một kịch bản xây dựng TFS, và nó cho thấy rằng thậm chí không thể tìm thấy %ERRORLEVEL% trong bản dựng TFS.

Tuy nhiên, tôi phải xóa /B khỏi các dòng exit, nếu không, mã vẫn luôn hiển thị cho tôi mã thoát 0.

6

tôi giải quyết vấn đề này bằng cách tạo ra một đơn tập tin batch (khá một chút đẹp hơn so với ở trên nhưng vẫn bí ẩn):

Nội dung của tập tin myant.bat:

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

điều quan trọng, mà không cần bất kỳ mã bất cứ điều gì sau call.

+0

+1 Đã có cùng một vấn đề khi cố gắng gọi kiến ​​từ psake. Điều này đã khắc phục được sự cố của tôi. –

2

Một miếng vá nhanh chóng được bổ sung như sau vào cuối tập tin ANT.BAT:

exit /b %ANT_ERROR% 

vấn đề này từ lâu đã tồn tại và cố định thời gian gần đây. Tham khảo Bug 41039.

Nó sẽ sẵn sàng trong bản phát hành ANT 1.8.2 trở lên.

2

Một vấn đề khác - nếu bạn gọi ANT trong tệp BAT và bạn quan tâm đến việc lưu giá trị lỗi, bạn phải giữ cuộc gọi ra khỏi khối if/else.

Ví dụ, điều này sẽ không hoạt động (... ở giữa một số thói quen):

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

Bạn phải thoát ra khỏi cuộc gọi như sau (... đặt bên ngoài thói quen mà):

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

(... ở giữa một số thói quen)

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

tôi giải quyết thay thế IF ERRORLEVEL 1 với IF %ERRORLEVEL% NEQ 0:

Các vấn đề liên quan