【发布时间】:2014-12-11 16:49:04
【问题描述】:
有没有办法跟踪给定进程的所有文件 I/O?我真正需要的是从给定进程读取/写入文件的位置(理想情况下,如果它是读取或写入操作,尽管这并不重要)。
我可以运行该流程并对其进行跟踪,而无需附加到我认为要简单得多的现有流程。是否有任何类型的包装实用程序可以运行一个进程来监视文件访问?
【问题讨论】:
有没有办法跟踪给定进程的所有文件 I/O?我真正需要的是从给定进程读取/写入文件的位置(理想情况下,如果它是读取或写入操作,尽管这并不重要)。
我可以运行该流程并对其进行跟踪,而无需附加到我认为要简单得多的现有流程。是否有任何类型的包装实用程序可以运行一个进程来监视文件访问?
【问题讨论】:
lsof:尝试这样做作为初学者:
lsof -p <PID>
此命令将列出所有当前打开的文件、fd、带有传递进程 ID 的进程的套接字。
对于您的特殊需求,请参阅我可以提供什么作为监控 php 脚本的解决方案:
php foo.php & _pid=$!
lsof -r1 -p $_pid
kill %1 # if you want to kill php script
strace:我推荐使用strace。与lsof 不同,只要进程在运行,它就会一直运行。当它们被调用时,它将打印出正在调用的系统调用。 -e trace=file 仅过滤访问文件系统的系统调用:
sudo strace -f -t -e trace=file php foo.php
或者对于已经运行的进程:
sudo strace -f -t -e trace=file -p <PID>
【讨论】:
strace,但该命令使用我自己的用户。这完成了工作:sudo strace -fte trace=%file -u $(id -un) <COMMAND>
除了 strace 之外,还有另一个选项不会显着减慢受监控的进程。使用 Liunx 内核的fanotify(不要与更流行的 inotify 混淆)可以监控整个挂载点的 IO 活动。使用unshared mountnamespaces,可以将给定进程的挂载与系统的其余部分隔离(docker 背后的一项关键技术)。
这个概念的实现可以在shournal 中找到,我是它的作者。
shell上的例子:
$ shournal -e sh -c 'cat foo > bar'
$ shournal --query --history 1
...
1 written file(s):
/home/user/bar
1 read file(s):
/home/user/foo
【讨论】:
unshare( CLONE_NEWNS); 几乎相同。您认为在此处包含完整源代码会有所帮助吗?
strace 是一个了不起的工具,但它的输出有点冗长。
如果您愿意,可以使用我编写的工具来处理 strace 输出并提供所有访问的文件(也包括 TCP 套接字)的 CSV 报告,其中包含以下数据:
1. 文件名
2. 读/写字节
3. 读/写操作次数
4.文件被打开的次数
它可以在新进程或已经运行的进程上运行(使用 /proc/fd 数据)。
我发现它对于调试场景和性能分析很有用。
你可以在这里找到它:iotrace
示例输出:
Filename, Read bytes, Written bytes, Opened, Read op, Write op
/dev/pts/1,1,526512,0,1,8904
socket_127.0.0.1:47948->127.0.0.1:22,1781764,396,0,8905,11
myfile.txt,65,0,9,10,0
pipe:[3339],0,0,0,1,0
之后,您可以在 Excel 或其他工具中处理 CSV 数据以进行排序或其他所需的分析。
缺点是您需要下载和编译,而且并不总是 100% 准确。
【讨论】:
这样的事情可能会减少文件活动监控对性能的影响。
$ watch -n 2.0 timeout 0.2 strace -p `pgrep myprogram` -fe trace=file
其中myprogram是进程名,2.0是每个监控周期之间的空闲时间,0.2是监控周期的长度,以秒为单位。
【讨论】: