Bash scripting - vòng lặp cho đến khi giá trị trả về là 0


25

Tôi cần phải bỏ qua một cái gì đó trong kịch bản của mình, nhưng đôi khi nó bị ngắt kết nối trước khi tất cả các dữ liệu đã được sao chép xong và khiến cho kết quả không thành công. Tôi đã tìm cách để thực hiện một "chặn", nhưng tôi không tìm thấy gì cả. Vì vậy, tôi đã cố gắng viết một kịch bản để lặp cho đến khi nó có thể được bỏ qua, nhưng nó không hoạt động.

while [ `sudo umount mount` ]
do
    sleep 0.1
done
rmdir mount

Khi chạy đầu ra:

umount: /home/evantandersen/mount: device is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))
rmdir: failed to remove `mount': Device or resource busy

Không nên lặp lại cho đến khi giá trị trả về sudo umount mountlà 0, có nghĩa là nó đã được xóa thành công?

Câu trả lời:


59

Các [lệnh là để đánh giá biểu thức điều kiện. Nó không được sử dụng ở đây.

Bởi vì umountkhông xuất ra bất cứ thứ gì trên đầu ra tiêu chuẩn của nó (các lỗi chuyển sang stderr), `sudo umount mount`mở rộng thành không có gì.

Vì vậy, nó giống như:

while [ ]
do
  sleep 0.1
done

Các [lệnh, khi không được thông qua bất kỳ đối số bên cạnh []lợi nhuận sai (một trạng thái thoát khác không), vì vậy bạn sẽ không tham gia các vòng lặp.

Ngay cả khi umountcó lỗi xuất ra trên thiết bị xuất chuẩn, sử dụng [lệnh sẽ không có ý nghĩa, bởi vì các từ kết quả của đầu ra đó sẽ không bao giờ tạo thành một biểu thức điều kiện hợp lệ.

Ở đây bạn muốn:

until sudo umount mount
do
  sleep 0.1
done

Đó là, bạn muốn kiểm tra trạng thái thoát của sudo / umount, không phải của [lệnh.

Nếu bạn muốn kiểm tra xem umountđầu ra có bất kỳ lỗi hoặc cảnh báo nào trên thiết bị lỗi chuẩn hay không, đó là nơi [có thể hữu ích. Đây -n "some-string"là một biểu thức có điều kiện được [lệnh nhận ra để kiểm tra xem "some-string"có trống hay không, vì vậy một cái gì đó như:

while [ -n "$(sudo umount mount 2>&1 > /dev/null)" ]; do
  sleep 0.1
done

Nhưng tìm kiếm sự hiện diện của thông báo lỗi hoặc cảnh báo nói chung là một ý tưởng tồi. Các umount lệnh cho chúng ta hay không thành công với mã lối ra của nó, đó là đáng tin cậy hơn. Nó có thể thành công và vẫn đưa ra một số thông điệp cảnh báo. Nó có thể thất bại và không xuất ra lỗi (như khi nó bị giết).

Trong trường hợp cụ thể này, lưu ý rằng umountcó thể thất bại vì thư mục không được gắn kết và bạn sẽ lặp lại mãi mãi trong trường hợp đó, vì vậy bạn có thể thử một cách tiếp cận khác như:

while mountpoint -q mount && ! sudo umount mount; do
  sleep 0.1
done

Hoặc nếu "mount" có thể được gắn nhiều lần và bạn muốn ngắt kết nối tất cả chúng:

while mountpoint -q mount; do
  sudo umount mount || sleep 0.1
done

Hoạt động, tuyệt vời!
charliehorse55

1
1 cho việc giải thích sự khác biệt giữa việc sử dụng [, [[hay không. Tôi muốn các trang man điển hình, các ví dụ về GNU và / hoặc TLDP về các điều kiện bash được đề cập chi tiết như vậy
renoirb

5

chức năng có thể sử dụng lại và sẽ hết thời gian trong 'n' giây

_umount() {
    [[ $# -lt 2 ]] && { 
        echo "Usage: ${FUNCNAME} <timeout_secs> <mnt_point>"; return 1
    }
    timeout=$(($(date +%s) + ${1}))
    until umount "${2}" 2>/dev/null || [[ $(date +%s) -gt $timeout ]]; do
       :
    done
}

không cần ngủ


1
[[...]]ksh/ bash/ zshcụ thể, tất cả đều có $SECONDSbiến đặc biệt, vì vậy bạn có thể làm:SECONDS=0; until umount... || ((SECONDS > $1)); do..
Stéphane Chazelas

Hãy nhớ rằng một mount remount,rolệnh trên thiết bị mips anno 2009 với thanh USB Intenso Micro Line có thể mất 23 hoặc thậm chí hơn 30 giây để hoàn thành.
Sao lưu chuyên nghiệp
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.