Re: Admin util wish list

Werner Almesberger (almesber@lrc.epfl.ch)
Thu, 18 Jul 1996 18:58:48 +0200 (MET DST)


lilo wrote:
> I know nothing about the BSD utility, but this suggests a general utility
> `fdstat' that would deal with files, sockets, etc. By user, filename, fd
> number, interface address, etc., etc.

psmisc version 12 already supports socket (=port#+protocol) to process
lookups. Note that mapping anything to a file name (unless the file
name comes from a small set of names, such as /dev) is much harder than
any of the other mappings due to the potentially very large number of
files on a system.

Todd Graham Lewis wrote:
> Not really, unless I'm missing something. BSD fstat gives the following:
>
> USER CMD PID FD MOUNT INUM MODE SZ|DV R/W
> tlewis zsh 27363 wd /usr 20307 drwxr-xr-x 512 r
> tlewis zsh 27363 0 / 4274 crw--w---- ttyp0 rw
> tlewis zsh 27363 1 / 4274 crw--w---- ttyp0 rw

I assume that was a pid->open_files mapping ? Most of the information
is already in /proc/<pid>, ready for lookup by the PID. You just need
to build hash tables for mount points and for /dev (the DV field).

It's so easy that I've just implemented it. I've attached the Perl
script.

- Werner

---------------------------------- fstat.pl -----------------------------------

#!/usr/bin/perl

sub handle
{
local ($path,$name) = @_;
(local ($link) = readlink($path)) || return;
local ($rw) = (lstat($path))[2];
local ($fdev,$ino) = $link =~ /\[(.+)\]:(\d+)/;
(local ($mode,$rdev,$size) = (stat($path))[2,6,7]) || return;
$rdev = $dev{$mode." ".$rdev};
printf("%-9s%-11s%5d%5s%9d %3o%9s%3s %-10s\n",$user,$cmd,$pid,$name,$ino,
$mode & 0777,$rdev ? $rdev : $size,
($rw & 0400 ? "r" : "").($rw & 0200 ? "w" : ""),
$mnt{hex($fdev)} ? $mnt{hex($fdev)} : "???");
}

opendir(DIR,"/dev") || die "opendir /dev: $!";
for (readdir DIR) {
@s = stat("/dev/$_");
$type = (lstat("/dev/$_"))[2] >> 12;
$dev{"".join(" ",@s[2,6])} = $_ if $type == 6 || $type == 2;
}
closedir DIR;
open(MNT,"/proc/mounts") || die "open /proc/mounts: $!";
for (<MNT>) {
$dir = (split(" ",$_))[1];
if (@s = stat($dir)) { $mnt{@s[0]} = $dir; }
}
close MNT;
print "USER CMD PID FD INUM MODE SZ|DV R/W MOUNT\n";
for $pid (@ARGV) {
if (!chdir "/proc/$pid") {
print STDERR "$pid: no such process\n";
next;
}
if (!opendir(DIR,"fd")) {
print STDERR "$pid: $!\n";
next;
}
@proc = stat(".");
$user = getpwuid($proc[4]) ? getpwuid($proc[4]) : $proc[4];
open(CMD,"cmdline") || die "open cmdline: $!";
($cmd) = (<CMD> =~ /^([^\000]*)(\000.*)?$/);
close CMD;
&handle("cwd","wd");
for (readdir DIR) { &handle("fd/$_",$_) unless $_ eq "." || $_ eq ".."; }
closedir DIR;
}

-- 
  _________________________________________________________________________
 / Werner Almesberger, DI-LRC,EPFL,CH   werner.almesberger@lrc.di.epfl.ch /
/_IN_R_133__Tel_+41_21_693_6621__Fax_+41_21_693_6610_____________________/