Bagaimana / Kapan Execute Shell menandai build sebagai kegagalan di Jenkins?

112

Kisah-kisah horor yang saya temukan saat mencari jawaban untuk yang satu ini ...

Oke, saya memiliki skrip .sh yang melakukan hampir semua hal yang seharusnya dilakukan Jenkins:

  • memeriksa sumber dari SVN
  • membangun proyek
  • menyebarkan proyek
  • bersihkan setelah itu sendiri

Jadi di Jenkins saya hanya perlu 'membangun' proyek dengan menjalankan skrip dalam perintah Execute Shell. Skrip dijalankan (sumber diunduh, proyek dibangun / disebarkan) tetapi kemudian menandai pembangunan sebagai kegagalan: Langkah membangun 'Jalankan shell' menandai pembangunan sebagai kegagalan Bahkan jika skrip berhasil dijalankan! Saya mencoba menutup skrip dengan:

  • keluar 0 (masih menandainya sebagai kegagalan)
  • exit 1 (tandai sebagai kegagalan, seperti yang diharapkan)
  • tidak ada perintah keluar sama sekali (tandai sebagai kegagalan)

Kapan, bagaimana dan mengapa Execute Shell menandai build saya sebagai gagal?

penguji
sumber

Jawaban:

131

Hal pertama yang pertama, arahkan mouse ke area abu-abu di bawah. Bukan bagian dari jawaban, tetapi mutlak harus dijawab:

Jika Anda memiliki skrip shell yang melakukan "checkout, build, deploy" dengan sendirinya, lalu mengapa Anda menggunakan Jenkins? Anda mengabaikan semua fitur Jenkins yang menjadikannya seperti sekarang. Anda mungkin juga meminta cron atau hook pasca-komit SVN untuk memanggil skrip secara langsung. Jenkins yang melakukan pembayaran SVN sendiri sangatlah penting. Ini memungkinkan build untuk dipicu hanya jika ada perubahan (atau dengan timer, atau manual, jika Anda mau). Ini melacak perubahan di antara build. Ini menunjukkan perubahan tersebut, sehingga Anda dapat melihat build mana untuk kumpulan perubahan mana. Ini mengirim email kepada pelaku ketika perubahan mereka menyebabkan build yang berhasil atau gagal (sekali lagi, sesuai konfigurasi yang Anda inginkan). Ini akan mengirim email kepada pelaku ketika perbaikan mereka memperbaiki build yang gagal. Dan lebih banyak lagi. Jenkins yang mengarsipkan artefak juga membuatnya tersedia, per bangunan, langsung dari Jenkins. Meskipun tidak sepenting checkout SVN, ini sekali lagi merupakan bagian integral dari apa yang menjadikannya Jenkins. Sama dengan penerapan. Kecuali Anda memiliki satu lingkungan, penerapan biasanya terjadi pada beberapa lingkungan. Jenkins dapat melacak lingkungan mana yang dibuat oleh build tertentu (dengan kumpulan perubahan SVN tertentu) yang diterapkan, melalui penggunaan Promosi. Anda meninggalkan semua ini. Kedengarannya seperti Anda diberitahu "Anda harus menggunakan Jenkins" tetapi Anda tidak benar-benar menginginkannya, dan Anda melakukannya hanya untuk melepaskan bos Anda, hanya untuk memberi tanda centang "ya, saya telah menggunakan Jenkins"

Jawaban singkatnya adalah: kode keluar dari perintah terakhir dari langkah build Execute Shell Jenkin adalah yang menentukan keberhasilan / kegagalan Langkah Build . 0- sukses, anything else- kegagalan. Catatan, ini menentukan keberhasilan / kegagalan langkah build , bukan seluruh pekerjaan yang dijalankan . Keberhasilan / kegagalan dari seluruh pekerjaan yang dijalankan selanjutnya dapat dipengaruhi oleh beberapa langkah build, serta tindakan dan plugin pasca-build.

Anda telah menyebutkan Build step 'Execute shell' marked build as failure, jadi kami akan fokus hanya pada satu langkah pembuatan. Jika langkah Execute shell build Anda hanya memiliki satu baris yang memanggil skrip shell Anda, kode keluar dari skrip shell Anda akan menentukan keberhasilan / kegagalan langkah build. Jika Anda memiliki lebih banyak baris, setelah eksekusi skrip shell, tinjau dengan cermat, karena baris itulah yang dapat menyebabkan kegagalan.

Terakhir, baca di sini Skrip Build Jenkins keluar setelah Google Test dijalankan . Ini tidak terkait langsung dengan pertanyaan Anda, tetapi perhatikan bahwa bagian tentang Jenkins yang meluncurkan langkah build Execute Shell , sebagai skrip shell dengan/bin/sh -xe

The -eberarti bahwa script shell akan keluar dengan kegagalan, bahkan jika hanya 1 perintah gagal, bahkan jika Anda melakukan pengecekan error untuk perintah itu (karena keluar naskah sebelum sampai ke pengecekan error Anda). Ini bertentangan dengan eksekusi normal skrip shell, yang biasanya mencetak pesan kesalahan untuk perintah yang gagal (atau mengalihkannya ke null dan menanganinya dengan cara lain), dan lanjutkan.

Untuk menghindari ini, tambahkan set +eke bagian atas skrip shell Anda.

Karena Anda mengatakan skrip Anda melakukan semua yang seharusnya dilakukan, kemungkinan besar perintah yang gagal ada di suatu tempat di akhir skrip. Mungkin gema terakhir? Atau salinan artefak di suatu tempat? Tanpa melihat keluaran konsol secara lengkap, kami hanya menebak-nebak.

Silakan posting keluaran konsol dari pekerjaan yang dijalankan, dan sebaiknya juga skrip shell itu sendiri, dan kemudian kami dapat memberi tahu Anda dengan tepat baris mana yang gagal.

orang Slavia
sumber
6
Alasan saya masih menggunakan Jenkins tidak jelas bagi saya ... Sepertinya seseorang di atas tidak begitu mengerti bahwa kami sudah memiliki skrip ini dan bersikeras agar kami menggunakan Jenkins. Saya merasa seperti berada di strip Dilbert. Terima kasih atas tip -e. Ini memecahkan masalah
penguji
45
Masih ada alasan bagus untuk menggunakan Jenkins: jejak audit, visibilitas status build, dll. Jika Anda sudah memiliki skrip build, memindahkannya ke Jenkins adalah langkah pertama yang baik sebelum melakukan refactoring untuk memanfaatkan fitur Jenkins.
aehlke
3
Menghubungkan silang jawaban ini serverfault.com/a/143576/186454 set + e dan set -e dapat ditentukan di mana saja dalam skrip Anda. Kode apa pun di antaranya tidak akan gagal membangun jika nilai yang dikembalikan bukan 0.
Alex Skrypnyk
2
sangat baik dikatakan pada skrip shell vs set jenkins
pushya
kami menggunakan jenkins untuk menyediakan akses terautentikasi dan UI untuk pekerjaan. Cron tidak akan memotongnya. Jenkins tidak hanya membuat cacat.
ffghfgh
90

Jawaban sederhana dan singkat untuk pertanyaan Anda adalah

Harap tambahkan baris berikut ke dalam langkah Build "Execute shell" Anda.

#!/bin/sh

Sekarang izinkan saya menjelaskan alasan mengapa kami memerlukan baris ini untuk pekerjaan build "Execute Shell".

Secara default, Jenkins take /bin/sh -xedan ini berarti -xakan mencetak setiap perintah. Dan opsi lainnya -e, yang menyebabkan shell segera berhenti menjalankan skrip ketika ada perintah keluar dengan kode keluar bukan-nol (ketika ada perintah gagal).

Jadi dengan menambahkan #!/bin/shkehendak memungkinkan Anda untuk mengeksekusi tanpa opsi.

Abhijeet Kamble
sumber
4
Suara positif. Tidak tahu tentang -xe default. Ketika grep comman saya tidak menemukan string, seluruh skrip saya gagal karena grep mengembalikan nilai bukan 0 :)
Somaiah Kumbera
Bekerja dengan baik! Menggunakannya di langkah-langkah yang tidak penting, langkah pembersihan yang hanya melakukan sesuatu seperti find . -name 'bower_components' -exec rm {} \;dan dalam beberapa kasus, gagal. Terima kasih!
yorch
ini membersihkan semuanya - 'Dan opsi lain -e, yang menyebabkan shell segera berhenti menjalankan skrip ketika ada perintah keluar dengan kode keluar bukan-nol (ketika ada perintah gagal).'
Paramvir Singh Karwal
3

Menurut pendapat saya, mematikan -eopsi ke shell Anda adalah ide yang sangat buruk. Akhirnya salah satu perintah dalam skrip Anda akan gagal karena kondisi sementara seperti kehabisan ruang disk atau kesalahan jaringan. Tanpa -eJenkins tidak akan menyadarinya dan akan melanjutkan dengan bahagia. Jika Jenkins telah disiapkan untuk melakukan penerapan, hal itu dapat mengakibatkan kode yang buruk didorong dan menurunkan situs Anda.

Jika Anda memiliki baris di skrip Anda di mana kegagalan diharapkan, seperti grep atau find, maka tambahkan saja || trueke akhir baris itu. Itu memastikan bahwa garis itu akan selalu kembali sukses.

Jika Anda perlu menggunakan kode keluar itu, Anda dapat memasukkan perintah ke dalam pernyataan if Anda:

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

Atau Anda dapat menangkap kode pengembalian dalam ||klausa Anda :

grep foo bar || ret=$?
Bryan Larsen
sumber
1
Terima kasih Bryan. Anda menyelamatkan hari saya. Selain itu, menurut saya sebaiknya aktifkan -x dan -e. Jadi yang Anda lihat di log jenkins Anda.
Bikal Basnet
2

Polos dan sederhana:

Jika Jenkins melihat langkah build (yang juga merupakan skrip) keluar dengan kode bukan nol, build tersebut ditandai dengan bola merah (= gagal).

Mengapa hal itu terjadi bergantung pada skrip build Anda.

Saya menulis sesuatu yang serupa dari sudut pandang lain, tetapi mungkin itu akan membantu untuk tetap membacanya: Mengapa menurut Jenkins bangunan saya berhasil?

sti
sumber
0

Jadi dengan menambahkan #!/bin/shkehendak memungkinkan Anda untuk mengeksekusi tanpa opsi.

Ini juga membantu saya dalam memperbaiki masalah di mana saya menjalankan skrip bash dari master Jenkins pada budak Linux saya. Dengan hanya menambahkan di #!/bin/bashatas skrip saya yang sebenarnya di blok "Execute Shell", itu memperbaiki masalah saya karena jika tidak menjalankan windows git menyediakan versi bash shell yang memberikan kesalahan.

Shailender Singh
sumber
0

Dalam Jenkins ver. 1.635, tidak mungkin untuk menampilkan variabel lingkungan asli seperti ini:

$BUILD_NUMBER or ${BUILD_NUMBER}

Dalam hal ini, Anda harus mengaturnya di variabel lain.

set BUILDNO = $BUILD_NUMBER
$BUILDNO
pengguna10413452
sumber