Who's in my Directory ?

Tom Christiansen tchrist at convex.COM
Thu Nov 29 07:14:10 AEST 1990


In article <BARNETT.90Nov28121406 at grymoire.crd.ge.com>,
barnett at crdgw1.ge.com scrawls:

>Here is a shell script that might work for BSD systems. I call it 'pswd'
>Output looks like:
>
> barnett     4777 co           0:00 PWD=/home/kreskin/u0/barnett
> etc.
>
>This only works is a processes current working directory is visible
>with a ps wweuax command.
>
>#!/bin/sh
># this script is like ps but prints out the current directory also
>ps wweuax!| awk '
>/PWD/	{
># print user PID TTY COMMAND
>		printf "%8s %8s %2s %14s ",$1,$2,$7,$10 ;
>		for (i=11;i<NF;i++)
>		if (index($i,"PWD=") == 1)  printf "%s",$i ;
>		printf "\n" ;
>	}'

Sorry, but very few programs keep your cwd in the $PWD envariable.  So
this won't work very often.    I would still go with fuser for SysV boxes,
fstat for BSD ones, or ofiles if you can't find any better.

Furthermore, you cannot process ps output with awk that way.  That STAT
column is fixed width but with an unknown number of elements.  If you try
to do it all with fixed width columns, you'll be unhappy again because
sometimes things like SZ or RSS get really big (at least on my machine) and
push things aside.  If you parse 'ps l' output, then you have to deal with
the WCHAN column being there or not, depending.

I'm not just going to criticize.  Here's a solution I came up with.  After
running 'ps l' through this filter, you can split on white space and
guarantee that the 0th field is the flags, ..., the 9th one is the wait
channel (which is 0 if originally missing), the 10th field is the process
run state with spaces set to dots to yield things like ".D.<." or ".R..."
or "VS.N.".  Field #13..$#F are the commands.

    #!/usr/local/bin/perl
    # fixps: put 'ps l' output into reliable fields
    # warning: sub-optimal perl code follows
    while (<>) {  # feed me output from 'ps l'
        if (/COMMAND/) { print; next; }
        ($fixed, $float) = 
	    /^(\s*\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+ )(.*)$/;
        ($wchan, $stat, $tt, $time, $command) = 
	    ($float =~ /^(.{8}) (.{5}) (..) +(\d+:\d+) +(.*)/);
        $wchan = '    0    ' if $wchan eq '        ';
        $stat =~ s/ /./g;
        print "$fixed $wchan   $stat  $tt  $time  $command\n";
    }

So you then do something like this:

        ps axl | fixps | something_else

Where something else can do this if you don't want to just split
into one big array.  This is now *much* easier to deal with.

    #!/usr/local/bin/perl
    while (<>) {
        ($flags, $uid, $pid, $ppid, $cp,
         $pri, $nice, $size, $rss, $wchan,
         $state, $tty, $time, $command)         = split(' ',$_,14);

        if ($state =~ /V/) {
            # found a vector job
        }

        if ($uid != 0 && $state =~ />/) {
        # OR: if ($uid != 0 && $nice < 0) {
            # negatively reniced non-root process
        }

        if ($ppid == 1 && $uid != 0 && !(hex($flags) & 0x00800000)
                && $tty ne "?") {               #      SLOGIN bit
            # someone logged out with something in background
        }
    }


--tom



More information about the Comp.unix.misc mailing list