在Linux下用户模式应用程序按进程名实现过滤器的最佳方法是什么?
我所知道的所有方法都依赖于阅读proc_fs:
/proc/$PID/exe
上的readlink /proc/$PID/cmdline
读取,直到第一个空字符/proc/$PID/status
如果与方法#3结合使用,第一种方法似乎是可靠的。不幸的是,当从系统中删除可执行文件时,路径会获得(deleted)
后缀,该系统可以是普通文件名的后缀部分。如果此类名称用于可执行文件,则过滤器不能很健壮。
第二种方法依赖于启动进程的shell。这只是该过程的第一个(位置0)参数,而IIUC,shell无论如何都可以自由地设置它们。例如,bash prepends dash to login shell。
第三种方法依赖于截断为15个字符的名称,直接取自内核task_struct中的字段。这显然不是很强大,但它是内核进程唯一可用的名称,因此必须补充其他两个。 (显然,如果名称包含非ASCII字符,它们将显示为转义序列,因此该方法可靠。)
总而言之,我无法提出一种强大的,独立于shell的方式,以支持按进程可执行文件名(或理想路径)进行筛选,从而允许任意文件名。我可能会使用cmdline中的前导命令参数,因为它可能符合我的目的,但我想确保我理解可用的选项。
注意:安全性虽然是一个问题,但却是另一回事。如果需要安全性,将检查进程的用户身份。但我想要的名称过滤器只是正确性。目的是可靠地实现服务质量或每个流程配置,并且将涉及流程名称过滤。
答案 0 :(得分:2)
第一种方法(readlink /proc/$PID/exe
)的健壮性可以通过在链接本身上执行一对stat
s和readlink的结果来改进。如果您获得匹配的st_dev
和st_ino
,则它们是相同的文件。如果您没有获得匹配或获得ENOENT
,请检查字符串末尾的" (deleted)"
,将其剥离并重试。重复,直到您获得匹配或用完" (deleted)"
个实例。
如果你没有得到匹配,那么可执行文件确实已被删除。 (在这种情况下你还没有真正指定你想做什么 - 你应该考虑一下。当你坚持坚固性时,你不能忽视已删除文件可以使用的事实!)
stat
之间仍然存在竞争条件,因此您可能希望打开这两个文件,而不是fstat
。然后,如果你得到一个设备+ inode匹配,你有一个文件描述符,可以放心地使用它实际上属于目标进程中执行的文件,而不是其他具有相似名称的文件。
下一个困难是如果在测试期间进程本身消失,并且PID被重用。如果您关心这一点,您可以在操作开始和结束时从/proc/$PID/stat
读取进程开始时间,以确保您在整个过程中处理相同的进程。 (此外,有一种方法可以防止进程离开:使用ptrace作为调试器附加到它。)
如果进程在查看时执行了不同的程序,那么问题就在于你想要做什么。 /proc/$PID/exe
会改变。如果在最终一致性检查后发生,您将返回 正确的值,但现在不再存在。除了ptrace之外,你无法做很多事情,这比你想要的更具侵入性。