Bash scripting - loop จนกว่าค่าที่ส่งคืนจะเป็น 0


25

ฉันจำเป็นต้องติดตั้งบางสิ่งบางอย่างในสคริปต์ของฉัน แต่บางครั้งก็ยกเลิกการต่อเชื่อมก่อนที่ข้อมูลทั้งหมดจะถูกคัดลอกและทำให้การติดตั้งล้มเหลว ฉันมองหาวิธีที่จะทำการติดตั้ง "บล็อก" แต่ฉันไม่พบอะไรเลย ดังนั้นฉันพยายามเขียนสคริปต์เพื่อวนซ้ำจนกว่าจะสามารถ unmount ได้ แต่ไม่ได้ผล

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

เมื่อรันเอาต์พุต:

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

ไม่ควรวนซ้ำจนกว่าค่าส่งคืนsudo umount mountเป็น 0 ซึ่งหมายความว่าถอนติดตั้งสำเร็จหรือไม่

คำตอบ:


59

[คำสั่งคือการประเมินการแสดงออกเงื่อนไข มันไม่มีประโยชน์อะไรที่นี่

เนื่องจากumountไม่มีเอาต์พุตใด ๆ ในเอาต์พุตมาตรฐาน (ข้อผิดพลาดไปที่ stderr) จึงไม่`sudo umount mount`ขยายสิ่งใดเลย

ดังนั้นจึงเป็นเช่น:

while [ ]
do
  sleep 0.1
done

[คำสั่งเมื่อไม่ผ่านการโต้แย้งใด ๆ ข้าง[และ]ผลตอบแทนที่เป็นเท็จ (สถานะทางออกที่ไม่ใช่ศูนย์) ดังนั้นคุณจะไม่ได้ใส่ห่วง

แม้ว่าจะumountมีข้อผิดพลาดในการส่งออกใน stdout การใช้[คำสั่งจะไม่สมเหตุสมผลเพราะคำที่เป็นผลมาจากการส่งออกจะไม่ได้ทำขึ้นการแสดงออกตามเงื่อนไขที่ถูกต้อง

ที่นี่ที่คุณต้องการ:

until sudo umount mount
do
  sleep 0.1
done

นั่นคือคุณต้องการตรวจสอบสถานะการออกของ sudo / umount ไม่ใช่[คำสั่ง

หากคุณต้องการตรวจสอบว่าumountมีข้อผิดพลาดหรือคำเตือนใด ๆ ใน stderr แสดงว่านั่นเป็นสิ่งที่[มีประโยชน์ -n "some-string"คือการแสดงออกตามเงื่อนไขที่ยอมรับโดย[คำสั่งในการทดสอบว่า"some-string"เป็นที่ว่างเปล่าหรือไม่ดังนั้นสิ่งที่ชอบ:

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

แต่การมองหาข้อความแสดงข้อผิดพลาดหรือข้อความเตือนเป็นความคิดที่ไม่ดี umount คำสั่งบอกเราว่าหรือไม่ก็ประสบความสำเร็จด้วยรหัสทางออกที่มีความน่าเชื่อถือ มันสามารถประสบความสำเร็จและยังคงออกข้อความเตือนบางอย่าง มันอาจล้มเหลวและไม่ส่งออกข้อผิดพลาด (เช่นเมื่อมันถูกฆ่า)

ในกรณีนี้โปรดทราบว่าumountอาจล้มเหลวเนื่องจากไม่ได้ติดตั้งไดเรกทอรีและคุณจะวนซ้ำตลอดไปในกรณีนั้นดังนั้นคุณสามารถลองวิธีอื่นเช่น:

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

หรือหาก "mount" อาจถูกเมาท์หลายครั้งและคุณต้องการยกเลิกการต่อเชื่อมทั้งหมด:

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

ทำงานได้ยอดเยี่ยม!
charliehorse55

1
+1 สำหรับการอธิบายความแตกต่างระหว่างการใช้[, [[หรือไม่ ฉันต้องการหน้าคู่มือทั่วไป, GNU และ / หรือตัวอย่าง TLDP เกี่ยวกับเงื่อนไขการทุบตีที่ครอบคลุมรายละเอียดดังกล่าว
renoirb

5

ฟังก์ชั่นนำมาใช้ใหม่และจะหมดเวลาใน 'n' วินาที

_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
}

ไม่จำเป็นต้องนอน


1
[[...]]เป็นksh/ bash/ zshเจาะจงทั้งหมดนี้มี$SECONDSตัวแปรพิเศษดังนั้นคุณสามารถทำได้:SECONDS=0; until umount... || ((SECONDS > $1)); do..
Stéphane Chazelas

โปรดจำไว้ว่าmount remount,roคำสั่งบนอุปกรณ์ mips anno 2009 ที่มีแท่ง USB Intenso Micro Line สามารถใช้เวลา23หรือ30 วินาทีในการดำเนินการให้เสร็จสมบูรณ์
Backup Pro
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.