如何在Linux上的`umount -l`之后使用文件可靠地确定进程

Max*_*ner 5 linux process unmounting

问题

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
Run Code Online (Sandbox Code Playgroud)

那么什么命令会显示所有进程在隐藏挂载的 /dev/loop0 中打开了一些文件?

失败的尝试

lsof

lsof -p <thepid>
Run Code Online (Sandbox Code Playgroud)

首先,这需要进程 id 的先验知识(这是在此处搜索的信息),其次即使如此,打开的文件也显示为/file没有迹象表明这是在隐藏的挂载文件系统上,而不是在正常的根文件系统上。

定影器

我无法从热熔器获得任何有用的输出。我认为联机帮助页中的某些内容使我无法理解。

检查 /sys/fs/

在这个特定的测试设置中,文件系统 ( ext4) 和设备 ( loop0) 是已知的。在那里可以检查文件系统是否已经从隐藏安装状态更改为未安装状态。

if [ -e /sys/fs/ext4/loop0/ ]; then
    echo "still not unmounted";
else
    echo "finally unmounted";
fi
Run Code Online (Sandbox Code Playgroud)

但这并没有给出具有打开文件句柄的进程列表。

手动检查 /proc

在proc中找到了一些信息:

假设 mnt_id 在系统范围内是唯一的(我不知道该假设是否正确!)可以制作所有进程中所有非隐藏 mnt_id的列表:

find /proc/ -maxdepth 1 -type d -regex '/proc/[0-9]+' -exec "cat" "{}/mountinfo" ";" | cut -d " " -f 1 | sort -gu
Run Code Online (Sandbox Code Playgroud)

然后列出所有打开的 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.
Run Code Online (Sandbox Code Playgroud)

如果将使用一种复杂的方法来比较这两个列表,则可以确定隐藏的 mnt_id 以及使用它们的 fd 和这些 fd 的进程 ID。但即使有这样的结果,知道这些隐藏的 mnt_id 中的哪一个对应于感兴趣的隐藏安装的文件系统的最后一步,仍然会丢失。

Jul*_*ier 3

由于使用 隐藏安装点的方式umount -l,因此无法找到哪些进程仍在使用受影响的文件。

获取列表的唯一方法是使用lsofbeforeumount -l来 grep 相关路径。例子:lsof | grep "/mountPoint/"

如果需要,您可以利用该输出来提取 PID 并继续监视它们。