Bash 脚本 - 循环直到返回值为 0

Bash 脚本 - 循环直到返回值为 0

我需要在脚本中卸载某些内容,但有时它会在所有数据完成复制之前卸载并导致卸载失败。我寻找一种方法来执行“阻止”卸载,但我没有找到任何东西。因此,我尝试编写一个脚本来循环直到可以卸载它,但它不起作用。

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 mount0,这意味着它已经成功卸载了吗?

答案1

[命令用于评估条件表达式。放在这里是没有用的。

因为umount在其标准输出上不输出任何内容(错误会转到 stderr),所以`sudo umount mount`会扩展为空。

所以就像:

while [ ]
do
  sleep 0.1
done

[命令在未传递任何参数时[返回]错误的(非零退出状态),因此您不会进入循环。

即使umount在标准输出上输出了错误,使用该[命令也没有意义,因为该输出产生的单词永远不会构成有效的条件表达式。

在这里你想要:

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

答案2

可重用函数,并将在“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
}

不需要睡觉

相关内容