http://qs321.pair.com?node_id=783581

pileofrogs has asked for the wisdom of the Perl Monks concerning the following question:

Greetings, fellow Monks.

I'm trying to write a script to check how long a process has been running. I can munge the output of ps, which sucks, I can read /proc/$PID/stat and find the number of jiffies, whatever they are, since the system booted, which also sucks, but in a different way. Specifically, munging ps output is unportable, unpredictable and is smells funny. Reading /proc/$PID/stat sounds great in principle, but I have fears I would do it wrong (what's a "jiffy?").

Does anyone know a perl module that will do this without sucking? (Parsing output of ps sucks. Something that reads /proc and works does not suck. Something that calls a C library OS interface function does not suck at all.)

The eventual purpose of all this is to have a simple script that exits true if a script is older than a value. So I can easily write shell scripts to kill processes that have wandered off and have been running way too long. So, if anyone knows a way to solve that problem, that would also be welcome.

UPDATE

Here's an example: Say I have two servers and I like to keep them in sync with an rsync job that runs every 10 minutes. If I run this and I find an rsync job already running*, if it's 11 minutes old, I might want to let it finish and try again in another 10 minutes. If it's a day old, I definitely want to kill it and launch a new rsync job right now.

*we assume I've filtered out any unrelated rsync processes

Thanks!
--Pileofrogs

Replies are listed 'Best First'.
Re: Linux Process Start Time
by idsfa (Vicar) on Jul 27, 2009 at 16:30 UTC
    $ctime{$PID} = (stat "/proc/$PID/stat")[10];

    This gives you the creation time of the process in seconds since the start of the epoch. While there can be concerns about portability across different OSes, you specified linux, and you wouldn't want to use /proc if you wanted to port this anywhere else anyway ...

    (Yes, I know, it's technically the time since the file was last changed, but the stat file is special that way.)


    The intelligent reader will judge for himself. Without examining the facts fully and fairly, there is no way of knowing whether vox populi is really vox dei, or merely vox asinorum. — Cyrus H. Gordon

      ++

      Awesome! That's exactly what I was looking for!

Re: Linux Process Start Time
by lostjimmy (Chaplain) on Jul 27, 2009 at 17:32 UTC

    Going with your original idea, I came up with this:

    open my $pstat, "<", "/proc/$ARGV[0]/stat" or die "$!"; chomp(my $stat_line = <$procstat>); close $pstat; my $time_offset = (split / /, $stat_line)[21]; $time_offset = int $time_offset / 100; my $btime; open my $stat, "<", "/proc/stat" or die "$!"; while (<$stat>) { if (/^btime (\d*)/) { $btime = $1; last; } } close $stat; my $start_time = $time_offset + $btime; my $length = time - $start_time; print $length;

    FYI, a jiffy is the time for one tick of the system interrupt timer, which happens to be 100Hz on my computer. That means this code is not portable. It would be if I knew a way to get the interrupt period at run time.

      ++

      Nice!

      Maybe /proc/cpuinfo? Non-portable, I know.

        The only place I know of that makes that information available is actually in /proc/config.gz. So, theoretically, you could get the timer frequency with zgrep CONFIG_HZ= /proc/config.gz, but it really doesn't seem like the best way of doing this.
Re: Linux Process Start Time
by ikegami (Patriarch) on Jul 27, 2009 at 16:15 UTC
    $^T
    $ perl -le'print "".localtime($^T)' Mon Jul 27 12:16:06 2009 $ perl -le'print "".localtime($^T)' Mon Jul 27 12:16:07 2009 $ perl -le'print "".localtime($^T)' Mon Jul 27 12:16:08 2009 $ perl -le'print "".localtime($^T)' Mon Jul 27 12:16:09 2009

    Update: Oops! Nevermind. You want to know how long *another* process has been running.

      In this case, the trick would work if the rsync command was run from a Perl script. Moreover, alarm could also be used to set a timeout (this has saved my day several times).

Re: Linux Process Start Time
by Illuminatus (Curate) on Jul 27, 2009 at 17:11 UTC
    While it would be nice to have a simple command that gives you the information you want, I disagree that parsing the output of ps is 'unportable'. It is certainly far more portable than /proc. The POSIX(ie SYSV) options for ps have been standardized for quite some time, as have the BSD options. Most systems I have worked with (AIX, Solaris, Linux, HP-UX) support the POSIX options. The only one that would require different syntax is FreeBSD.

    You might try just keeping track of PID and procname between calls to your monitor. Using 'ps -ex | grep 'name1|name2|...' should give you what you want with either a POSIX or BSD ps(pid will always be first field). If the same PID/procname shows up twice in a row, kill it off. Just a thought...

    fnord

      I've had the output of ps change on me in a distro version update. But, actually, you're probably right, I wasn't using a POSIX or BSD output format. That would stabilize it.

      And yes, /proc isn't portable. It might be a little bit portable. I know it's optional on OpenBSD, for instance.

      Looking for the same process name twice won't help. I want to know the age. I think I'll add an example to the OP.

      Good point about POSIX or BSD ps output.

      --Pileofrogs

        Sorry, I should have been clearer. Let's say you run the monitor in cron every 10 minutes:
        • try to open /tmp/monitor_info
        • if non-existent, generate pid/procname list, write to /tmp/monitor_info and exit
        • read file data into array/hash
        • generate pid/procname list using aforementioned ps command
        • compare lists. If same pair shows up in both, kill it (it's been running longer than 10 minutes).
        • write new list to /tmp/monitor_info
        Adjust cron interval to be a time comfortable to ensuring that process is broken. It is a little more complicated if you have processes that have different 'comfort intervals', but you could simply include a count to each line in /tmp/monitor_info to manage this.

        This script is short and easy. Does that make sense?

        fnord

Re: Linux Process Start Time
by Khen1950fx (Canon) on Jul 27, 2009 at 23:21 UTC

      Great link! Thanks!