Jalankan perintah shell berulang kali sampai gagal?

191

Saya telah menulis tes fuzzy yang gagal gagal. Saya telah menambahkan beberapa kode debug, tetapi sekarang saya ingin menjalankan tes sampai gagal sehingga saya dapat mengumpulkan hasil debug.

Saya telah menyiapkan tes sehingga saya dapat menjalankannya menggunakan:

./runtest

Solusi saya saat ini adalah menulis untilfailskrip:

#!/bin/bash
$@
while [ $? -eq 0 ]; do
    $@
done

Kemudian gunakan:

untilfail ./runtest

Apakah ada solusi yang lebih sederhana?

bradley.ayers
sumber
11
Catatan: biasanya mengutip "$ @".
jordanm

Jawaban:

328

while membutuhkan perintah untuk dieksekusi, sehingga Anda dapat menggunakan yang lebih sederhana

while ./runtest; do :; done

Ini akan menghentikan loop ketika ./runtestmengembalikan kode keluar yang bukan nol (yang biasanya menunjukkan kegagalan).

Untuk lebih menyederhanakan solusi Anda saat ini, Anda hanya perlu mengubah skrip tillfail Anda menjadi seperti ini:

#!/bin/bash

while "$@"; do :; done

Dan kemudian Anda bisa menyebutnya dengan perintah apa pun yang sudah Anda gunakan:

untilfail ./runTest --and val1,val2 -o option1 "argument two"
nneonneo
sumber
25
Ada baiknya juga menunjukkan bahwa itu [adalah perintah. Ini adalah kesalahpahaman umum dengan pengguna baru yang [merupakan bagian dari ifdan whilesintaksis.
jordanm
2
Bagaimana saya bisa menghitung berapa kali ia berjalan sebelum gagal?
GrantJ
13
@GJJJ: sebenarnya sangat sederhana. Letakkan count=0sebelum loop, kemudian bukannya :di loop (no-op), put (( count++ ))- ini menambah penghitung.
nneonneo
14
Peretasan produktivitas: Jika Anda menggunakan sistem dengan saydan seorang pembicara yang dapat Anda gunakan while ./runtest; do :; done && say test faileduntuk diberitahu jika itu pernah berhenti
Schneems
5
@ Schneems: patut dicatat bahwa itu sayadalah spesifik macOS.
nneonneo
13

Jika Anda tidak ingin membungkus pipa yang rumit menjadi skrip atau fungsi shell maka ini berfungsi:

while true; do 
  curl -s "https:..." | grep "HasErrors.:true"
  if [[ "$?" -ne 0 ]]; then 
    break
  fi
  sleep 120
done

Permintaan HTTP dalam hal ini selalu mengembalikan 200 tetapi juga mengembalikan beberapa JSON yang memiliki atribut "HasErrors": true ketika ada kesalahan.

Judd Rogers
sumber
1

Setelah memiliki masalah yang sama dalam sistem yang memiliki logika coba-coba ulang yang digandakan di mana-mana, saya membuat alat khusus untuk memecahkan ini yang disebut "coba lagi":

retry --until=fail ./runtest

Contoh yang lebih kompleks:

retry --until=fail --message="test succeeded" --delay=1 ./runtest

Alat tersedia dari https://github.com/minfrin/retry .

Graham Leggett
sumber