drdot
drdot

Reputation: 3347

How to find out which files the program has accessed?

(Ubuntu linux) I started a program and how can I find out which file and IO this program has accessed?

I know there are some software that allows one to get this information easily in windows.

Upvotes: 0

Views: 612

Answers (2)

user4322779
user4322779

Reputation:

lsof is great for finding all open files of a program by its PID. Just run lsof -a -p . It can also show open sockets. A manpage for it is at http://linux.die.net/man/8/lsof. You may have to run lsof as root unless it has setuid to root permissions and is executable by other.

For IO utilization try iotop. iotop requires python and more info about it is at http://guichaz.free.fr/iotop/. You should be able to install both tools using apt-get.

Neither of these tools makes it easy to find files a program may have accessed right after starting and then quickly closed. This happens for many applications that read a configuration file after starting, for example. To find these sorts of files, I wrote a utility that recursively finds all files in a directory which have been created, accessed or modified within a given last number of seconds. If you have no idea where the program may have accessed files, then it can search the entire system from /.If you really want to localize the files it may have accessed, then it could be run chroot to confine it. Below is the utility, which I call tfind and is implemented in perl. When run with no arguments it prints its usage. A way to use it is to start your program, some seconds later run "tfind --atime 15 --ctime 15 --mtime 15 /" to see all the files that have been accessed, created or modified in the past 15 seconds and then eliminate those files that are known to be accessed by other programs, for example /var/log/messages. The remaining files are probably those accessed by your program.

#!/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];
}

Upvotes: 0

Sam Varshavchik
Sam Varshavchik

Reputation: 118330

You could be asking one of two questions:

1.

Q: How do I find out which files a currently running program has open?

A: Look in /proc/<pid>/fd.

2.

Q: I want to know which files a program opens, when it runs.

A: Use the strace tool. Read its man page and other documentation, for more information.

P.S. Using strace will slow down the program's execution, noticable.

Upvotes: 1

Related Questions