Lặp đi lặp lại một lệnh shell cho đến khi nó thất bại?


190

Tôi đã viết một bài kiểm tra mờ mà không đáng tin cậy. Tôi đã thêm một số mã gỡ lỗi, nhưng bây giờ tôi muốn chạy thử nghiệm cho đến khi thất bại để tôi có thể thu thập đầu ra gỡ lỗi.

Tôi đã thiết lập thử nghiệm để tôi có thể chạy thử bằng cách sử dụng:

./runtest

Giải pháp hiện tại của tôi là viết một untilfailkịch bản:

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

Sau đó sử dụng nó:

untilfail ./runtest

Có một giải pháp đơn giản hơn?


11
Lưu ý bên lề: thường xuyên trích dẫn "$ @".
jordanm

Câu trả lời:


326

while nhận lệnh để thực thi, vì vậy bạn có thể sử dụng đơn giản hơn

while ./runtest; do :; done

Điều này sẽ dừng vòng lặp khi ./runtesttrả về mã thoát khác (thường là dấu hiệu của sự thất bại).

Để đơn giản hóa hơn nữa giải pháp hiện tại của bạn, bạn chỉ nên thay đổi tập lệnh Untilfail của mình thành như sau:

#!/bin/bash

while "$@"; do :; done

Và sau đó bạn có thể gọi nó bằng bất kỳ lệnh nào bạn đang sử dụng:

untilfail ./runTest --and val1,val2 -o option1 "argument two"

25
Thật tốt khi chỉ ra đó [là một mệnh lệnh. Đó là một quan niệm sai lầm phổ biến với người dùng mới mà [là một phần của ifwhilecú pháp.
jordanm

2
Làm thế nào tôi có thể đếm được bao nhiêu lần nó chạy trước khi nó thất bại?
GrantJ

13
@GrantJ: nó thực sự rất đơn giản. Đặt count=0trước vòng lặp, sau đó thay vì :trong vòng lặp (không có op), đặt (( count++ ))- điều này làm tăng bộ đếm.
nneonneo 04/07/2015

14
Tấn công năng suất: Nếu bạn đang saysử dụng hệ thống và loa, bạn có thể sử dụng while ./runtest; do :; done && say test failedđể được thông báo nếu hệ thống dừng lại
Schneems

5
@Schneems: đáng chú ý saylà dành riêng cho macOS.
nneonneo

13

Nếu bạn không muốn bọc một đường ống phức tạp thành tập lệnh shell hoặc hàm thì điều này hoạt động:

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

Yêu cầu HTTP trong trường hợp này luôn trả về 200 nhưng cũng trả về một số JSON có thuộc tính "HasErrors": true khi có lỗi.


1

Có một vấn đề tương tự trong một hệ thống có logic thử lại shell được nhân đôi ở mọi nơi, tôi đã tạo ra một công cụ chuyên dụng để giải quyết vấn đề này gọi là "thử lại":

retry --until=fail ./runtest

Một ví dụ phức tạp hơn:

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

Công cụ có sẵn từ https://github.com/minfrin/retry .

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.