我有一些每天被多个用户访问的 samba 驱动器。我已经有代码来识别共享驱动器(来自 SQL 表)并将它们安装在所有用户都可以访问它们的特殊目录中。
我想知道,如果我从我的 SQL 表中删除一个驱动器(有效地使其脱机),有没有办法卸载繁忙的设备?到目前为止,我发现任何形式的umount
都不起作用。
忽略破坏数据的可能性 - 是否可以卸载当前正在读取的设备?
是的!有一种方法可以立即分离繁忙的设备 - 即使它很忙并且无法强制卸载。您可以稍后清理所有内容:
umount -l /PATH/OF/BUSY-DEVICE
umount -f /PATH/OF/BUSY-NFS (NETWORK-FILE-SYSTEM)
注意/注意
umount
首先,您可以使用pwd
command 来验证您当前的目录路径(不应该是挂载路径),然后使用cd
command 退出挂载路径 - 稍后使用上述命令卸载它。如果可能,让我们定位/识别繁忙的进程,杀死该进程,然后杀死unmount
samba 共享/驱动器以最大程度地减少损坏:
lsof | grep '<mountpoint of /dev/sda1>'
(或任何安装的设备)
pkill target_process
(按名称杀死繁忙的进程 | kill PID
| killall target_process
)
umount /dev/sda1
(或任何安装的设备)
尝试卸载时,请确保您不在已安装的设备中。
umount -l
在撰写本文时,投票最多的答案建议使用umount -l
.
的有用行为umount -l
是隐藏文件系统以防止被绝对路径名访问,从而最大限度地减少进一步的 moutpoint 使用。
可以通过挂载一个空目录来实现相同的行为000
,该目录对要卸载的目录具有权限。
然后,对挂载点下方文件名的任何新访问都将以零权限访问新覆盖的目录 - 从而阻止了新的卸载阻止程序。
remount,ro
要解锁的主要卸载成就是只读重新安装。当您获得remount,ro
徽章时,您会知道:
mount -o remount,ro /dev/device
如果有文件打开以进行写入,则保证会失败,因此请直接尝试。你可能感觉很幸运,朋克!
如果您不走运,请仅关注打开文件以进行写入的进程:
lsof +f -- /dev/<devicename> | awk 'NR==1 || $4~/[0-9]+[uw -]/'
然后,您应该能够以只读方式重新安装设备并确保状态一致。
如果此时您无法以只读方式重新挂载,请调查此处列出的其他一些可能原因。
只读重装成就解锁☑</p>
恭喜,您在挂载点上的数据现在是一致的,并且可以防止将来写入。
fuser
不如lsof
fuser
为什么不早点使用 use呢?好吧,你可以有,但 fuser
操作的是directory,而不是device,所以如果你想从文件名空间中删除挂载点并仍然使用fuser
,你需要:
mount -o bind /media/hdd /mnt
到另一个位置就是这样:
null_dir=$(sudo mktemp --directory --tmpdir empty.XXXXX")
sudo chmod 000 "$null_dir"
# A request to remount,ro will fail on a `-o bind,ro` duplicate if there are
# still files open for writing on the original as each mounted instance is
# checked. https://unix.stackexchange.com/a/386570/143394
# So, avoid remount, and bind mount instead:
sudo mount -o bind,ro "$original" "$original_duplicate"
# Don't propagate/mirror the empty directory just about hide the original
sudo mount --make-private "$original_duplicate"
# Hide the original mountpoint
sudo mount -o bind,ro "$null_dir" "$original"
然后你会有:
fuser
。这更令人费解[1],但允许您使用:
fuser -vmMkiw <mountpoint>
它将以交互方式要求终止打开文件以进行写入的进程。当然,您可以在完全不隐藏挂载点的情况下执行此操作,但上述模仿umount -l
,没有任何危险。
该-w
开关仅限于写入过程,并且-i
是交互式的,因此在只读重新安装后,如果您很着急,您可以使用:
fuser -vmMk <mountpoint>
杀死在挂载点下打开文件的所有剩余进程。
希望此时,您可以卸载设备。(umount
如果您已000
在顶部绑定挂载模式目录,则需要在挂载点上运行两次。)
或使用:
fuser -vmMki <mountpoint>
以交互方式杀死阻止卸载的剩余只读进程。
target is busy
!打开文件不是唯一的卸载阻止程序。有关其他原因及其补救措施,请参见此处和此处。
即使你有一些潜伏的 gremlin 阻止你完全卸载设备,你至少让你的文件系统处于一致的状态。
然后,您可以使用lsof +f -- /dev/device
列出包含文件系统的设备上打开文件的所有进程,然后终止它们。
[1] 使用起来不那么复杂mount --move
,但这需要mount --make-private /parent-mount-point
具有含义。基本上,如果挂载点挂载在/
文件系统下,您会希望避免这种情况。
尝试以下操作,但在运行之前请注意,该-k
标志将终止任何使设备处于忙碌状态的正在运行的进程。
旗帜-i
在fuser
杀戮前先询问。
fuser -kim /address # kill any processes accessing file
unmount /address
Check for exported NFS file systems with exportfs -v. If found, remove with exportfs -d share:/directory. These don't show up in the fuser/lsof listing, and can prevent umount from succeeding.
签出umount2
:
Linux 2.1.116 添加了 umount2() 系统调用,与 umount() 一样,卸载目标,但允许附加标志来控制操作的行为:
MNT_FORCE(自 Linux 2.1.116 起)即使忙也强制卸载。(仅适用于 NFS 挂载。) MNT_DETACH(自 Linux 2.4.11 起) 执行延迟卸载:使挂载点对新的访问不可用,并在挂载点停止忙碌时实际执行卸载。MNT_EXPIRE(自 Linux 2.6.8 起)将挂载点标记为已过期。如果当前未使用挂载点,则使用此标志对 umount2() 的初始调用会失败并返回错误 EAGAIN,但会将挂载点标记为已过期。只要没有任何进程访问挂载点,它就会一直过期。指定 MNT_EXPIRE 的第二个 umount2() 调用卸载过期的安装点。不能使用 MNT_FORCE 或 MNT_DETACH 指定此标志。返回值
成功时,返回零。出错时,返回 -1,并适当设置 errno。
以防万一有人有相同的铅。:
我无法卸载/mnt
chroot 监狱的挂载点(此处)。
以下是我键入要调查的命令:
$ umount /mnt
umount: /mnt: target is busy.
$ df -h | grep /mnt
/dev/mapper/VGTout-rootFS 4.8G 976M 3.6G 22% /mnt
$ fuser -vm /mnt/
USER PID ACCESS COMMAND
/mnt: root kernel mount /mnt
$ lsof +f -- /dev/mapper/VGTout-rootFS
$
如您所见,甚至lsof
什么也不返回。
然后我有了输入这个的想法:
$ df -ah | grep /mnt
/dev/mapper/VGTout-rootFS 4.8G 976M 3.6G 22% /mnt
dev 2.9G 0 2.9G 0% /mnt/dev
$ umount /mnt/dev
$ umount /mnt
$ df -ah | grep /mnt
$
这是我创建的/mnt/dev
绑定,/dev
以便能够从 chroot 监狱中修复我的系统。
卸载后,我的pb。现在解决了。
我最近也有类似的卸载需求,以便用 gparted 更改它的标签。
/dev/sda1 正在通过 /etc/fstab 挂载为 /media/myusername。当尝试卸载失败时,我研究了错误。我忘记先在 /dev/hda1 上卸载带有挂载点的双分区拇指驱动器。
我按照建议尝试了“lsof”。
$ sudo lsof | grep /dev/sda1
其输出是:
lsof: WARNING: can't stat() fuse.gvfsd-fuse 文件系统 /run/user/1000/gvfs
输出信息可能不完整。
lsof: WARNING: can't stat() fuse file system /run/user/1000/doc
输出信息可能不完整。
由于 lsof 发出了两个保险丝警告,我在 /run/user/1000/* 中四处寻找,并猜测它可能是打开的文件或挂载点(或两者)干扰事物。
由于挂载点位于 /media/ 中,我再次尝试:
$ sudo lsof | grep /media
同样的两个警告,但这次它返回了附加信息:
Bash 4350 Myusername CWD DIR 8,21 4096 1048577 /媒体
Sudo 36302根CWD DIR 8,21 4096 1048577 /
MEDIA GREP 36303 MYUSERNAME CWD
DIR 8,21 4096
1048577根 cwd DIR 8,21 4096 1048577 /媒体
我还在摸不着头脑,这时我才想起拇指驱动器从 USB 端口伸出来。也许抓挠有帮助。
所以我卸载了拇指驱动器分区(卸载一个自动卸载另一个)并安全拔下拇指驱动器。这样做之后,我能够卸载 /dev/sda1 (不再安装任何东西),用 gparted 重新标记它,重新安装驱动器和拇指驱动器,没有任何问题。
培根得救了。
有人提到,如果您使用终端并且当前目录位于要卸载的路径中,则会出现错误。
作为补充,在这种情况下,您lsof | grep path-to-be-unmounted
必须具有以下输出:
bash ... path-to-be-unmounted
在卸载文件系统之前。我们需要检查是否有任何进程持有或使用文件系统。这就是它显示设备繁忙或文件系统正在使用的原因。运行以下命令以找出文件系统使用的进程:
fuser -cu /local/mnt/
它将显示有多少进程持有/使用文件系统。
local/mnt: 1725e(root) 5645c(shasankarora)
ps -ef | grep 1725
<-->ps -ef | grep <pid>
kill -9 pid
杀死所有进程,然后您将能够卸载分区/繁忙设备。
当一切正常时,另一种选择是编辑/etc/fstab
、添加noauto
标志和重新启动机器。该设备将不会被挂载,当你完成任何操作后,删除标志并再次重新启动。
利基答案:
如果您在该设备上有一个 zfs 池,至少当它是一个基于文件的池时,lsof
不会显示使用情况。但是你可以简单地运行
sudo zpool export mypool
然后卸载。
sudo fusermount -u -z <mounted path>
注意:不要对路径使用完成,因为这也会冻结终端。
另一个原因可能是您的主挂载文件夹中的辅助挂载,例如在您为嵌入式设备使用 SD 卡之后:
# mount /dev/sdb2 /mnt # root partition which contains /boot
# mount /dev/sdb1 /mnt/boot # boot partition
卸载 /mnt 将失败:
# umount /mnt
umount: /mnt: target is busy.
首先,我们必须卸载引导文件夹,然后卸载根目录:
# umount /mnt/boot
# umount /mnt
就我而言,我无法卸载挂载到 AFP 共享目录的分区。(共享到 Apple bonjour/avahi mdns 世界)我将服务器上的所有登录名移到了他们的主目录;我将所有远程连接的 Mac 移动到其他目录。即使使用 umount -f 我仍然无法卸载分区所以我重新启动了服务器上的 netatalk 守护程序。
(/etc/netatalk/afp.conf 中有共享分配) netatalk 重新启动后,没有 -f 的情况下 umount 成功。