Làm thế nào / Khi nào thì Execute Shell đánh dấu một bản xây dựng là thất bại trong Jenkins?


112

Những câu chuyện kinh dị tôi đã tìm thấy trong khi tìm kiếm câu trả lời cho câu chuyện này ...

OK, tôi có một tập lệnh .sh thực hiện khá nhiều mọi thứ mà Jenkins phải làm:

  • kiểm tra các nguồn từ SVN
  • xây dựng dự án
  • triển khai dự án
  • làm sạch sau khi chính nó

Vì vậy, trong Jenkins, tôi chỉ phải 'xây dựng' dự án bằng cách chạy tập lệnh trong lệnh Execute Shell. Tập lệnh được chạy (các nguồn được tải xuống, dự án đang xây dựng / triển khai) nhưng sau đó nó đánh dấu việc xây dựng là thất bại: Bước xây dựng 'Execute shell' được đánh dấu xây dựng là thất bại Ngay cả khi tập lệnh đã được chạy thành công! Tôi đã thử đóng tập lệnh bằng:

  • thoát 0 (vẫn đánh dấu là thất bại)
  • thoát 1 (đánh dấu là thất bại, như mong đợi)
  • không có lệnh thoát nào cả (đánh dấu là thất bại)

Khi nào, làm thế nào và tại sao Execute Shell đánh dấu bản dựng của tôi là thất bại?

Câu trả lời:


131

Đầu tiên, hãy di chuột qua vùng màu xám bên dưới. Không phải là một phần của câu trả lời, nhưng hoàn toàn phải nói:

Nếu bạn có một tập lệnh shell tự nó "kiểm tra, xây dựng, triển khai", thì tại sao bạn lại sử dụng Jenkins? Bạn đang bỏ qua tất cả các tính năng của Jenkins làm cho nó như thế nào. Bạn cũng có thể có một cron hoặc một hook sau cam kết SVN gọi script trực tiếp. Jenkins thực hiện kiểm tra SVN chính nó là rất quan trọng. Nó cho phép các bản dựng chỉ được kích hoạt khi có thay đổi (hoặc hẹn giờ, hoặc thủ công, nếu bạn muốn). Nó theo dõi các thay đổi giữa các bản dựng. Nó hiển thị những thay đổi đó, vì vậy bạn có thể xem bản dựng nào dành cho tập hợp thay đổi nào. Nó gửi email cho những người cam kết khi các thay đổi của họ gây ra việc xây dựng thành công hoặc không thành công (một lần nữa, như được định cấu hình theo ý bạn). Nó sẽ gửi email cho những người cam kết khi bản sửa lỗi của họ đã khắc phục được bản dựng không thành công. Và nhiều hơn nữa. Jenkins lưu trữ các hiện vật cũng làm cho chúng có sẵn, mỗi bản dựng, ngay lập tức Jenkins. Mặc dù không quan trọng như thanh toán SVN, nhưng đây một lần nữa là một phần không thể thiếu làm nên Jenkins. Tương tự với triển khai. Trừ khi bạn có một môi trường duy nhất, việc triển khai thường xảy ra với nhiều môi trường. Jenkins có thể theo dõi môi trường nào mà một bản dựng cụ thể (với tập hợp các thay đổi SVN cụ thể) được triển khai nó, thông qua việc sử dụng Chương trình khuyến mãi. Bạn đang nói trước tất cả những điều này. Nghe có vẻ như bạn được nói rằng "bạn phải sử dụng Jenkins" nhưng bạn không thực sự muốn và bạn đang làm điều đó chỉ để khiến các ông chủ của bạn không ủng hộ bạn, chỉ để đánh dấu chọn "vâng, tôi đã sử dụng Jenkins"

Câu trả lời ngắn gọn là: mã thoát của lệnh cuối cùng của bước xây dựng Jenkin's Execute Shell là yếu tố quyết định sự thành công / thất bại của Bước xây dựng . 0- thành công, anything else- thất bại. Lưu ý, điều này quyết định sự thành công / thất bại của bước xây dựng , không phải toàn bộ quá trình chạy . Sự thành công / thất bại của toàn bộ quá trình chạy công việc có thể bị ảnh hưởng thêm bởi nhiều bước xây dựng, các hành động và plugin sau xây dựng.

Bạn đã đề cập Build step 'Execute shell' marked build as failure, vì vậy chúng tôi sẽ chỉ tập trung vào một bước xây dựng duy nhất. Nếu bước xây dựng shell Execute của bạn chỉ có một dòng duy nhất gọi shell script của bạn, thì mã thoát của shell script của bạn sẽ xác định sự thành công / thất bại của bước xây dựng. Nếu bạn có nhiều dòng hơn, sau khi thực hiện shell script, hãy xem xét cẩn thận chúng, vì chúng là những dòng có thể gây ra lỗi.

Cuối cùng, hãy đọc ở đây Jenkins Build Script thoát sau khi thực thi Google Test . Nó không liên quan trực tiếp đến câu hỏi của bạn, nhưng lưu ý rằng một phần về việc Jenkins khởi chạy bước xây dựng Execute Shell , như một tập lệnh shell với/bin/sh -xe

Điều -eđó có nghĩa là shell script sẽ thoát ra khi bị lỗi, ngay cả khi chỉ 1 lệnh bị lỗi, ngay cả khi bạn thực hiện kiểm tra lỗi cho lệnh đó (vì script thoát ra trước khi nó được kiểm tra lỗi của bạn). Điều này trái với việc thực thi bình thường của các tập lệnh shell, thường in thông báo lỗi cho lệnh bị lỗi (hoặc chuyển hướng nó thành null và xử lý nó bằng cách khác) và tiếp tục.

Để tránh điều này, hãy thêm set +evào đầu tập lệnh shell của bạn.

Vì bạn nói rằng tập lệnh của bạn làm tất cả những gì nó phải làm, rất có thể lệnh thất bại nằm ở đâu đó ở cuối tập lệnh. Có thể là một tiếng vọng cuối cùng? Hay bản sao hiện vật ở đâu đó? Không nhìn thấy đầu ra đầy đủ của bảng điều khiển, chúng tôi chỉ phỏng đoán.

Vui lòng đăng đầu ra bảng điều khiển của lệnh chạy công việc và tốt nhất là bản thân tập lệnh shell, và sau đó chúng tôi có thể cho bạn biết chính xác dòng nào bị lỗi.


6
Tôi không rõ lý do tôi vẫn sử dụng Jenkins ... Có vẻ như ai đó ở trên cùng không hiểu rằng chúng tôi đã có kịch bản này và khăng khăng chúng tôi sử dụng Jenkins. Tôi cảm thấy như tôi đang ở trong một dải Dilbert. Cảm ơn bạn vì mẹo -e. Nó đã giải quyết được vấn đề
người thử nghiệm

45
Vẫn có những lý do chính đáng để sử dụng Jenkins: theo dõi kiểm tra, khả năng hiển thị trạng thái bản dựng, v.v. Nếu bạn đã có tập lệnh xây dựng, chuyển nó sang Jenkins là bước đầu tiên tốt trước khi cấu trúc lại nó để tận dụng các tính năng của Jenkins.
aehlke

3
Liên kết chéo câu trả lời này serverfault.com/a/143576/186454 set + e và set -e có thể được chỉ định ở bất kỳ đâu trong tập lệnh của bạn. Bất kỳ mã nào ở giữa sẽ không bị lỗi khi xây dựng nếu giá trị trả về không phải là 0
Alex Skrypnyk

2
nói rất hay trên shell script vs jenkins set
latexhya

chúng tôi sử dụng jenkins để cung cấp quyền truy cập được xác thực và giao diện người dùng cho công việc. Một cron sẽ không cắt nó. Jenkins không chỉ chạy cripts.
ffghfgh

90

Câu trả lời đơn giản và ngắn gọn cho câu hỏi của bạn là

Vui lòng thêm dòng sau vào bước Xây dựng "Execute shell" của bạn.

#!/bin/sh

Bây giờ hãy để tôi giải thích cho bạn lý do tại sao chúng ta yêu cầu dòng này cho công việc xây dựng "Execute Shell".

Theo mặc định, Jenkins lấy /bin/sh -xevà phương tiện -xnày sẽ in từng lệnh và tùy chọn khác -e, khiến trình bao dừng chạy một tập lệnh ngay lập tức khi bất kỳ lệnh nào thoát với mã thoát khác 0 (khi bất kỳ lệnh nào bị lỗi).

Vì vậy, bằng cách thêm ý #!/bin/shchí cho phép bạn thực thi mà không có tùy chọn.


4
Đã ủng hộ. Không biết về mặc định -xe. Khi comman grep của tôi đã không tìm thấy một chuỗi toàn bộ kịch bản của tôi thất bại vì grep trở một giá trị 0 lại không :)
Somaiah Kumbera

Làm việc rất tốt! Sử dụng nó cho các bước không quan trọng của tôi, một bước dọn dẹp chỉ làm một số việc giống như find . -name 'bower_components' -exec rm {} \;và trong một số trường hợp, nó đã thất bại. Cảm ơn!
yorch

điều này đã xóa mọi thứ - 'Và tùy chọn khác -e, khiến trình bao ngừng chạy tập lệnh ngay lập tức khi bất kỳ lệnh nào thoát với mã thoát khác 0 (khi bất kỳ lệnh nào không thành công).'
Paramvir Singh Karwal

3

Theo tôi, tắt -etùy chọn đối với trình bao của bạn là một ý tưởng thực sự tồi. Cuối cùng một trong các lệnh trong tập lệnh của bạn sẽ không thành công do các điều kiện tạm thời như hết dung lượng đĩa hoặc lỗi mạng. Nếu không có -eJenkins sẽ không nhận ra và sẽ tiếp tục vui vẻ. Nếu bạn đã thiết lập Jenkins để triển khai, điều đó có thể dẫn đến việc mã xấu được đẩy và đưa trang web của bạn xuống.

Nếu bạn có một dòng trong tập lệnh của mình mà dự kiến ​​sẽ có lỗi, chẳng hạn như một lỗi hoặc một tìm kiếm, thì chỉ cần thêm || truevào cuối dòng đó. Điều đó đảm bảo rằng dòng sẽ luôn trả lại thành công.

Nếu bạn cần sử dụng mã thoát đó, bạn có thể đưa lệnh vào câu lệnh if của mình:

grep foo bar; if [ $? == 0 ]; then ...    -->   if grep foo bar; then ...

Hoặc bạn có thể nắm bắt mã trả lại trong ||mệnh đề của mình :

grep foo bar || ret=$?

1
Cảm ơn Bryan. Bạn đã cứu ngày của tôi. Ngoài ra, tôi nghĩ bạn nên bật cả -x và -e. Để bạn thấy trong nhật ký jenkins của mình.
Bikal Basnet

2

Thông thường và đơn giản:

Nếu Jenkins thấy bước xây dựng (cũng là một tập lệnh) thoát ra với mã khác 0, bản dựng được đánh dấu bằng một quả bóng màu đỏ (= không thành công).

Chính xác tại sao điều đó xảy ra phụ thuộc vào kịch bản xây dựng của bạn.

Tôi đã viết một cái gì đó tương tự từ một quan điểm khác nhưng có lẽ dù sao đọc nó cũng sẽ hữu ích: Tại sao Jenkins nghĩ rằng công trình của tôi đã thành công?


0

Vì vậy, bằng cách thêm ý #!/bin/shchí cho phép bạn thực thi mà không có tùy chọn.

Nó cũng giúp tôi khắc phục sự cố khi tôi đang thực thi tập lệnh bash từ Jenkins master trên máy nô lệ Linux của mình. Bằng cách thêm vào #!/bin/bashbên trên tập lệnh thực tế của tôi trong khối "Execute Shell", nó đã khắc phục sự cố của tôi vì nếu không, nó đang thực thi windows git được cung cấp phiên bản bash shell đang gặp lỗi.


0

Trong Jenkins ver. 1.635, không thể hiển thị biến môi trường gốc như thế này:

$BUILD_NUMBER or ${BUILD_NUMBER}

Trong trường hợp này, bạn phải đặt nó trong một biến khác.

set BUILDNO = $BUILD_NUMBER
$BUILDNO
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.