问题
在某个已安装的文件系统上执行后umount -l
,该文件系统仍然保持已安装状态(尽管是隐藏的),因为某些进程维护(至少)该文件系统上某些文件的一个打开文件句柄,如何可靠地获取此类进程的列表?
测试设置
我执行了以下步骤来创建这样的情况,并在系统中浏览并尝试各种命令(在带有 Linux 3.16 内核的 debian jessie 上使用 bach):
sudo -i
cd $(mktemp -d) # get empty directory to play around with
# create empty file system with one file
dd if=/dev/zero of=disk bs=1M count=4
mkfs.ext4 disk
# mount the filesytem and create a file
mkdir mounted
mount disk mounted # uses /dev/loop0 in my case, actual device my vary
touch mounted/file
# fork of a process with an open file handle to file
bash -c 'cd mounted; exec 3<>file; while true; do sleep inf; done' &
# verify that the file is open in the background
lsof mounted/file
# lazy unmount
umount -l mounted
# even remove the mountpoint
rmdir mounted
那么什么命令可以显示打开隐藏安装的 /dev/loop0 中某些文件的所有进程呢?
失败的尝试
拉索夫
lsof -p <thepid>
首先,这需要事先了解进程 ID(这是此处搜索的信息),其次,即使打开的文件显示为/file
没有任何迹象表明该文件位于隐藏安装的文件系统上,而不是正常的根文件系统上。
定影器
我无法从定影器获得任何有用的输出。我认为手册页中的某些内容让我困惑。
检查/sys/fs/
在这个特定的测试设置中,文件系统 ( ext4
) 和设备 ( loop0
) 是已知的。在那里可以检查文件系统是否已经从隐藏安装状态更改为未安装状态。
if [ -e /sys/fs/ext4/loop0/ ]; then
echo "still not unmounted";
else
echo "finally unmounted";
fi
但这并没有提供具有打开文件句柄的进程列表。
手动检查/proc
在proc中找到一些信息:
假设 mnt_id 在系统范围内是唯一的(我不知道这个假设是否正确!)可以列出所有非隐藏 mnt_ids跨所有流程:
find /proc/ -maxdepth 1 -type d -regex '/proc/[0-9]+' -exec "cat" "{}/mountinfo" ";" | cut -d " " -f 1 | sort -gu
然后列出所有实际情况任何打开的 fd 使用 mnt_ids:
find /proc/ -regex '/proc/[0-9]+/fdinfo/[0-9]+' -exec cat "{}" ";" | grep mnt_id | cut -f 2 | sort -gu
# maybe gives some errors like 'Operation not permitted' or 'No such file or directory' because of inspecting it's own process and sub-process and possibly parallel things happening. probably this is an unreliable way of inspecting /proc.
如果将使用一种复杂的方法来比较这两个列表,可以确定隐藏的 mnt_ids 以及使用它们的 fd 和这些 fd 的进程 ID。但即使有了这个结果,仍然缺少了解这些隐藏 mnt_ids 中的哪一个对应于感兴趣的隐藏安装文件系统的最后一步。
答案1
由于使用 隐藏安装点的方式umount -l
,因此无法找到哪些进程仍在使用受影响的文件。
获取列表的唯一方法是使用lsof
beforeumount -l
来 grep 相关路径。例子:lsof | grep "/mountPoint/"
。
如果需要,您可以利用该输出来提取 PID 并继续监视它们。