【问题标题】:How to find out which files the program has accessed?如何找出程序访问了哪些文件?
【发布时间】:2014-12-24 23:29:35
【问题描述】:

(Ubuntu linux) 我启动了一个程序,如何知道这个程序访问了哪个文件和IO?

我知道有一些软件可以让人们在 Windows 中轻松获取这些信息。

【问题讨论】:

标签: linux operating-system


【解决方案1】:

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

1.

问:如何查看当前正在运行的程序打开了哪些文件?

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

2.

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

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

附:使用 strace 会减慢程序的执行速度,很明显。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-26
      • 1970-01-01
      • 2011-10-05
      • 1970-01-01
      • 2010-09-17
      相关资源
      最近更新 更多