如何找出程序访问的文件?

时间:2014-12-24 23:29:36

标签: linux operating-system

(Ubuntu linux)我启动了一个程序,如何找出该程序访问的文件和IO?

我知道有一些软件允许用户在Windows中轻松获取此信息。

2 个答案:

答案 0 :(得分:1)

您可能会问两个问题之一:

1

问:如何找出当前正在运行的程序已打开的文件?

A:查看/proc/<pid>/fd

2

问:我想知道程序在运行时打开哪些文件。

答:使用strace工具。有关更多信息,请阅读其手册页和其他文档。

P.S。使用strace会减慢程序的执行速度,这是显而易见的。

答案 1 :(得分:0)

lsof非常适合通过PID查找程序的所有打开文件。只需运行lsof -a -p。它还可以显示打开的套接字。它的联机帮助页位于http://linux.die.net/man/8/lsof。您可能必须以root身份运行lsof,除非它具有setuid为root权限并且可由其他人执行。

对于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];
}