【发布时间】:2014-12-24 23:29:35
【问题描述】:
(Ubuntu linux) 我启动了一个程序,如何知道这个程序访问了哪个文件和IO?
我知道有一些软件可以让人们在 Windows 中轻松获取这些信息。
【问题讨论】:
(Ubuntu linux) 我启动了一个程序,如何知道这个程序访问了哪个文件和IO?
我知道有一些软件可以让人们在 Windows 中轻松获取这些信息。
【问题讨论】:
您可能会问以下两个问题之一:
1.
问:如何查看当前正在运行的程序打开了哪些文件?
答:查看/proc/<pid>/fd。
2.
问:我想知道程序在运行时打开了哪些文件。
答:使用 strace 工具。阅读其手册页和其他文档,了解更多信息。
附:使用 strace 会减慢程序的执行速度,很明显。
【讨论】:
lsof 非常适合通过 PID 查找程序的所有打开文件。只需运行 lsof -a -p 。它还可以显示打开的套接字。它的联机帮助页位于http://linux.die.net/man/8/lsof。您可能必须以 root 身份运行 lsof,除非它具有 root 权限的 setuid 并且可由其他人执行。
对于 IO 利用率,请尝试 iotop。 iotop 需要 python,有关它的更多信息位于http://guichaz.free.fr/iotop/。您应该能够使用 apt-get 安装这两个工具。
这些工具都不能轻松找到程序在启动后可能立即访问然后快速关闭的文件。例如,许多在启动后读取配置文件的应用程序都会发生这种情况。为了找到这些类型的文件,我编写了一个实用程序,它递归地查找目录中在给定的最后几秒内创建、访问或修改的所有文件。如果你不知道程序可能在哪里访问过文件,那么它可以从 / 搜索整个系统。如果你真的想本地化它可能访问过的文件,那么可以运行 chroot 来限制它。下面是实用程序,我称之为 tfind 并在 perl 中实现。当不带参数运行时,它会打印它的用法。使用它的一种方法是启动您的程序,几秒钟后运行“tfind --atime 15 --ctime 15 --mtime 15 /”以查看过去 15 秒内已访问、创建或修改的所有文件和然后删除那些已知会被其他程序访问的文件,例如 /var/log/messages。其余的文件可能是您的程序访问的文件。
#!/usr/bin/perl
# tfind - find files less than n seconds old
# usage: tfind [ --atime i --ctime j --mtime k ] path
use strict;
use warnings;
use File::Find;
use vars qw/*name/;
*name = *File::Find::name;
use Getopt::Long;
my $prog = $0;
$prog =~ s,(?:[^\0]*/)*([^\0]+),$1,;
my $usage = "
$prog finds files in path that have been modified, changed or
accessed within a given number of seconds. The bundled find
utilities only detect time changes to the nearest day. However,
it can be useful for monitoring to find files modified, changed
or accessed within shorter time periods.
Usage: $prog [ --help --atime i --ctime j --mtime k ] path
Options
--atime i true if file was accessed within the last i seconds,
where i must be a postive integer or 0
--ctime j true if the files status was changed within the last
j seconds, where j must be a positve integer or 0
--mtime k true if the files data was modified within the last
k seconds, where k must be a positive integer or 0
--help shows this help screen
Examples
$prog --atime 2 dir prints names of files in dir accessed
within the last 2 seconds
$prog --ctime 600 dir prints names of files in dir with status
changes in the last 10 minutes
$prog --mtime 3600 dir prints names of files in dir modified
within the last hour
$prog --atime 2 --ctime 600 --mtime 3600 dir
prints names of files in dir meeting all
three conditions
";
my $opt_help = '';
my $opt_atime = '';
my $opt_mtime = '';
my $opt_ctime = '';
GetOptions (
"help" => \$opt_help,
"atime=s" => \$opt_atime,
"ctime=s" => \$opt_ctime,
"mtime=s" => \$opt_mtime );
if ($opt_help) {
print "$usage\n";
exit;
}
unless (@ARGV == 1) {
print "$usage\n";
exit;
}
my $path = shift;
my $atime_mark = 0;
my $ctime_mark = 0;
my $mtime_mark = 0;
($opt_atime,$atime_mark) = testoption("atime",$opt_atime);
($opt_ctime,$ctime_mark) = testoption("ctime",$opt_ctime);
($opt_mtime,$mtime_mark) = testoption("mtime",$opt_mtime);
my $findstr;
if (!$opt_atime && !$opt_ctime && !$opt_mtime) {
exit;
} else {
$findstr = '
find(\&wanted, $path);
sub wanted {
my $start = time;
my ($fsdev,$inode,$mode,$nlink,$uid,$gid,$devid,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = lstat $_;';
} if (!$opt_atime && !$opt_ctime && $opt_mtime) {
$findstr .= '
if (($start - $mtime) < $mtime_mark) {
print "$name\n";
}
}
';
} elsif ($opt_atime && !$opt_ctime && !$opt_mtime) {
$findstr .= '
if (($start - $atime) < $atime_mark) {
print "$name\n";
}
}
';
} elsif (!$opt_atime && $opt_ctime && !$opt_mtime) {
$findstr .= '
if (($start - $ctime) < $ctime_mark) {
print "$name\n";
}
}
';
} elsif ($opt_atime && !$opt_ctime && $opt_mtime) {
$findstr .= '
if ((($start - $atime) < $atime_mark) &&
(($start - $mtime) < $mtime_mark)) {
print "$name\n";
}
}
';
} elsif (!$opt_atime && $opt_ctime && $opt_mtime) {
$findstr .= '
if ((($start - $ctime) < $ctime_mark) &&
(($start - $mtime) < $mtime_mark)) {
print "$name\n";
}
}
';
} elsif ($opt_atime && $opt_ctime && !$opt_mtime) {
$findstr .= '
if ((($start - $atime) < $atime_mark) &&
(($start - $ctime) < $ctime_mark)) {
print "$name\n";
}
}
';
} elsif ($opt_atime && $opt_ctime && $opt_mtime) {
$findstr .= '
if ((($start - $atime) < $atime_mark) &&
(($start - $ctime) < $ctime_mark) &&
(($start - $mtime) < $mtime_mark)) {
print "$name\n";
}
}
';
} else {
print "$prog: logical error in options values:
opt_atime = $opt_atime
opt_ctime = $opt_ctime
opt_mtime = $opt_mtime\n";
exit 2;
}
eval $findstr;
sub testoption {
my $opt = $_[0];
my $optarg = $_[1];
my @out;
if ($optarg || ($optarg =~ /^\s*[+-]?0\s*$/)) {
$optarg = trim($optarg);
if (($optarg =~ /^[+-]?\d+$/) && ($optarg >= 0)) {
$out[0] = 1;
$out[1] = $optarg;
return @out;
} else {
print "$opt argument \"$optarg\" is not a positive integer or 0.\n";
exit;
}
} else {
$out[0] = 0;
$out[1] = 0;
return @out;
}
}
sub trim {
my @out = @_;
for (@out) {
s/^\s+//;
s/\s+$//;
}
return wantarray ? @out : $out[0];
}
【讨论】: