我需要在脚本中卸载某些内容,但有时它会在所有数据完成复制之前卸载并导致卸载失败。我寻找一种方法来执行“阻止”卸载,但我没有找到任何东西。因此,我尝试编写一个脚本来循环直到可以卸载它,但它不起作用。
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,这意味着它已经成功卸载了吗?
答案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
}
不需要睡觉