如何克隆 /proc 文件系统的只读部分

如何克隆 /proc 文件系统的只读部分

读取 /proc 文件系统的问题在于它不是原子的。我尝试使用一个希望读取它的库(Python 中的 procfs),但它大约有 5% 的时间出现故障,因为我所追求的进程现在已经消失了。因此,我希望将 /proc 中的所有内容复制到另一个位置,例如/proc_clone/<GUID>/.可以使用该命令生成 GUID uuidgen

天真的方法是尝试使用cp -r,但我收到一大堆“权限被拒绝”错误,并且花费了超过一秒的时间。我只需要一个子集/proc/<pid>,即使这样,也只需要可以转换为字符串的只读内容(最终我希望构建一个包含所有这些内容的 JSON 文件)。

我正在寻找一个可以为我做到这一点的脚本,而且短、简单、非常快,可以通过跳过进程来处理在飞行中死亡的进程但是,我想避免编写 C 代码 - 我宁愿坚持使用 bash、现有实用程序,也许还有 Perl / Python。这里的目标只是拍摄 的子集的快照/proc,而不是生成 JSON 文件本身。

我听到过这样的观点:“永远不要尝试复制,/proc而只是阅读”。好吧,它的非原子性质意味着当尝试执行非常简单的操作时,必须抛出一堆try/catch代码。使用像Python(我最终想要使用的)这样的高级语言来迭代/proc是一种缓慢的方法,它涉及IO和CPU时间。这增加了看到进程死掉的风险(我当然经常看到它;我有一个每分钟询问 /proc 的脚本,我遇到了很多异常)。我想构建一个库,输出单个 JSON 文件,其中包含有关进程的 CPU 和内存使用信息,以人类可读的格式(例如,使用秒而不是 jiffies、字节而不是页、除了值之外还有单位。我是不担心从目录转储中创建该文件需要一些时间;我只是想确保快照尽可能准确,所以如果我不应该复制 /proc,那么应该使用其他方法。我用?

答案1

你需要看看proc 的手册页。查看/proc/[pid]/* 条目并选择您想要的文件。

你做不是想要复制一切。举个例子,你有 /proc/[pid]/mem一个进程的所有虚拟内存,包括共享内存等——即所有内存的大小。此外,除非进程拥有memptraced以更高的权限读取,否则您无法读取它。 (进而仅有的虚拟尺寸 - /proc/pid/status -> VmSize) – 等等。

或者/proc/PID/exe它只是一个到可执行文件的链接,/proc/PID/fd/*它保存stdinstdoutstderr其他文件、管道等的文件描述符。

还有很多其他的特别的文件以及大量链接(如果您全部关注它们,您将永远无法完成)。读一下上面提到的那个人,来自 kernel.org 的文档, ETC。


此外,这些文件不是块设备文件。它们驻留在内存中,因为 proc 是基于内存的文件系统。在一种方式中,您可以将其称为内核的窗口,以便于访问。

因此,当涉及到您想要的读取时,这也是一个很大的优势 - 由于信息驻留在内存中,没有磁盘 I/O,因此速度非常快。当然,如果您选择将数据写入磁盘,则会丢失数据 - 但仍然比磁盘到磁盘快得多。


将其视为共享内存,并尽量不要重复不必要的内容。对于您的任务,您可能还会查看 /proc.查看pstop等的源代码,free快速了解其他工具的工作原理。


写了一些其他答案,可能或多或少涉及到某些方面。您可能会发现其中一些有用:


编辑:

至于评论。你可以这样做:

save_to=/some/path

pushd /proc
for d in [0-9]*; do
    cp "$d/cmdline" "$save_to/$d.cmdline"
    cp "$d/status" "$save_to/$d.status"
done
popd

但我会使用一些较低的级别,例如 C 来解析文件,因为上面的方法很可能不够快,无法满足人们的需求。

如果是每小时左右复制一次,那么可以,但不能以例如几秒甚至几分钟的间隔进行复制。

相关内容