我有一些桑巴驱动器,每天都有多个用户在访问。我已经有代码(从SQL表中)识别共享驱动器,并将它们安装在所有用户都可以访问它们的特殊目录中。
我想知道,如果我从SQL表中删除驱动器(有效地使其脱机),如何甚至没有办法卸载繁忙的设备?到目前为止,我发现任何形式的umount
都不起作用。
忽略破坏数据的可能性-是否可以卸载当前正在读取的设备?
cd
挂载了dir,然后您成为root用户或再次登录,然后又陷入了另一个shell。难道exit
所有的炮弹。
我有一些桑巴驱动器,每天都有多个用户在访问。我已经有代码(从SQL表中)识别共享驱动器,并将它们安装在所有用户都可以访问它们的特殊目录中。
我想知道,如果我从SQL表中删除驱动器(有效地使其脱机),如何甚至没有办法卸载繁忙的设备?到目前为止,我发现任何形式的umount
都不起作用。
忽略破坏数据的可能性-是否可以卸载当前正在读取的设备?
cd
挂载了dir,然后您成为root用户或再次登录,然后又陷入了另一个shell。难道exit
所有的炮弹。
Answers:
是!!有一种方法可以立即分离繁忙的设备(即使它很忙并且无法强行卸下)。您可以稍后清除所有内容:
umount -l /PATH/OF/BUSY-DEVICE
umount -f /PATH/OF/BUSY-NFS(NETWORK-FILE-SYSTEM)
注意:
如果可能,让我们找到/确定繁忙的进程,终止进程,然后卸下samba共享以最大程度地减少损坏。
lsof | grep '<mountpoint of /dev/sda1>'
(或任何已安装的设备)
pkill target_process
(按名称| kill PID
| 杀死繁忙的进程。killall target_process
)
umount /dev/sda1
(或任何已安装的设备)
lsof
:# opkg install lsof
请尝试以下操作,但是在运行它之前,请注意该-k
标志将终止所有正在运行的进程,从而使设备忙碌。
该-i
标志使fuser
杀害前询问。
fuser -kim /address # kill any processes accessing file
unmount /address
lsof | grep '/dev/<my-device>
没有返回任何东西,但是效果很好!可能还想提出一些建议fuser -m /dev/<my-device>
,以防您想在杀死进程之前查明该进程。
umount -l
在撰写本文时,最受好评的答案建议使用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 -]/'
然后,您应该能够以只读方式重新安装设备并确保状态一致。
如果此时您无法重新安装只读,请调查此处列出的其他可能原因。
只读的重新安装成就已解锁🔓☑
恭喜,您在挂载点上的数据现在是一致的,并且可以防止将来写入。
fuser
不如lsof
为什么不使用fuser
更早使用?好吧,您可以拥有fuser
一个目录,但可以 在一个设备上运行,而不是在设备上运行,因此,如果您想从文件名空间中删除挂载点并仍然使用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
含义。基本上,如果将安装点安装在/
文件系统下,则要避免这种情况。
--lazy
是如此危险,为什么umount
手册页中没有警告呢?它只说:“ 懒惰卸载。立即从文件层次结构中分离文件系统,并在不再繁忙时立即清除对该文件系统的所有引用。 ”
签出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,但会将安装点标记为已过期。只要任何进程都无法访问挂载点,该挂载点就会保持过期状态。第二个umount2()调用指定MNT_EXPIRE来卸载过期的安装点。不能使用MNT_FORCE或MNT_DETACH指定此标志。返回值
成功时,返回零。如果出错,则返回-1,并正确设置errno。