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

Hi,

I've used perlish implementations/hooks into other linux system tools (Proc::ProcessTable, etc.) I'm having trouble finding something that hooks into "lsof". It feels a bit kludgy to me to 'open my $lsof, "/usr/sbin/lsof |"'.

Any thoughts?

Replies are listed 'Best First'.
Re: LSOF Perl Implementation
by salva (Canon) on Jun 06, 2005 at 18:27 UTC
    well, I can imagine at least three ways to do so:
    • pipe lsof to your script.
    • get lsof source code and wrap it inside an XS or Inline::C module.
    • rewrite it completely (or just the parts that you need) in pure Perl translating the C source.

    Sometimes the last alternative is surprinsingly easy, for instance Net::SSH::Perl seems to be programmed this way.

    update: I have been looking at the original lsof package and it comes with several sample perl scripts that use it. They go with the pipe aproach.

Re: LSOF Perl Implementation
by biosysadmin (Deacon) on Jun 06, 2005 at 20:22 UTC
    I often find myself saying similar things in a quest to make my scripts as general and as portable as possible. If there were a Unix::lsof CPAN package available, I think you would be remiss in not using it. However, since there does not appear to be one, you have two options:
    • Write your own package. This isn't really as difficult as you might think, and you could initially make it work on Linux (I'm assuming that you're using Linux) and port it to other operating systems later. For example, Solaris and FreeBSD probably wouldn't be difficult at all.
    • Just use the pipe idea shown above. It has some very important strengths: it's simple, it works, and it gets the job down.

    In a perfect world we'd always use a well-tested and highly portable CPAN module for things like this, and all of our Perl scripts would be portable to a wide variety of operating systems. However, it's important to sometimes forgo idealism in order to get the job done. Cheers. :)

      At the moment, the way I am doing it is with the pipe. The reason that I was looking for a more pure-perl implementation or a wrapped c-code implementation was that this is running in a script that sometimes runs MANY times (often simultaneously) (it's a ftp-server postprocessor). The need for the lsof call is that there is some apparent corruption happening on certain files (and they are all rijndael encrypted, hence 1 1 byte corruption is VERY bad!!) and it appears to me that the FTP server is holding open a file during a rename and I am processing the file prior to it flushing the buffer or something.

      Tha bug is very frustrating, and also quite difficult to track down. It's a complex system involving PocketPC devices, a linux server running proftpd, plus lots of backend post-processing of the files created by the pocketpc devices...

      Again, thanks for your input. If I find that the numerous piped lsof calls are putting to much of a strain on the server, I'll probably port it to a module (and CPAN it). Might be an interesting foray into the world of XS or inline c!
Re: LSOF Perl Implementation
by davidrw (Prior) on Jun 06, 2005 at 18:00 UTC
    I found this oreilly chapter but it is just opening the pipe ... but hopefully it will be useful for reference if you have to end up going that route..

    Update: Ah, crap. i didn't realize where that link was coming from (it was on the first page of google(perl lsof) results). Anyways, the hyperlink is removed now, and apologies, and thanks to sth and caron for noticing. For those w/hard (legal) copies of the book, it was chapter 4.4.2 of "Perl for System Administration".

      I don't think we should be posting links to illegal hostings of O'Reilly books on the web.

Re: LSOF Perl Implementation
by zentara (Cardinal) on Jun 07, 2005 at 12:23 UTC
    Looking at the manpage for lsof, it seems to have a large selection of commands and modes in which to run it. If I were you, I would try opening it with IPC::Open3 and see what you can do with it that way. IPC::Open3 will allow you to separate the STDOUT and STDERR, so after you send lsof a command you could read the STDOUT and STDERR and try to detect your corruption problem. There are alot of advanced techniques you can use with IPC::Open3 like adding the STDOUT and STDERR to IO::Select, and using low level ioctl to see which filehandles have output, (see which filehandles have output from perldoc -q filehandle ) for your ftp problem.

    I'm not really a human, but I play one on earth. flash japh