Where's My Catalyst Server?

Ovid on 2008-02-13T15:49:51

It's a nasty hack, but I got sick and tired of always doing the following:

  1. Start our Catalyst server
  2. Launch a second program which needs the server
  3. Cuss because I've gotten the host/port wrong again.

So I wrote something like this:

use List::MoreUtils 'uniq';
use Net::Domain 'hostname';
use Getopt::Long;

sub get_cat_host_port {
    my ( $app_name, $user ) = @_;
    $app_name .= "_server.pl";
    $user ||= [getpwuid($<)]->[0];

    # The sed bit is embarrassing but needed on a Cat restart
    # when the shell quotes things :/
    chomp(my @processes
      = uniq `ps -ef|grep "$user.*$app_name"|grep -v grep|sed -e 's/"//g' -e 's/.* script//'`
    );
    if ( @processes > 1 ) {
        require Data::Dumper;
        $Data::Dumper::Indent = 1;
        warn Data::Dumper->Dump( [\@processes], ['*processes'] );
        die "Found more than one $app_name server for ($user)";
    }
    unless (@processes) {
        die "Could not find any $app_name servers for ($user)";
    }
    local @ARGV = split /\s+/ => $processes[0];
    local $SIG{__WARN__} = sub {
        my $warning = shift;
        return if $warning =~ /Unknown option/; # wish this was configurable
        CORE::warn($warning);
    };
    GetOptions(
        'port=i' => \my $port,
        'host=s' => \my $host,
    );
    $port ||= 3000;
    $host ||= hostname();
    return ( $host, $port );
}

It's now tucked away in a tools library so we can reuse this.


Fixing up that shell command

Crag on 2008-02-13T18:25:36

You had

ps -ef|grep "$user.*$app_name"|grep -v grep|sed -e 's/"//g' -e 's/.* script//'

If you're using all GNU tools, you can improve that shell command a bit:

ps --no-header --user "$user" --format command | grep "^$app_name" | sed 's/"//g;s/.* script//'

  • No grep for user (which may be output numerically under some conditions)
  • --no-header and --format mean you get only what you want out of ps
  • No grep -v to remove grep
  • No -e on the sed commands
  • Combined the sed commands into a single sed expression.

If you require shortest-possible shell commands, you can use the short-format switches on ps and trim whitespace:

ps h -u "$user" -o command|grep "^$app_name"|sed 's/"//g;s/.* script//'

Re:Fixing up that shell command

Ovid on 2008-02-14T09:51:29

We're on Solaris. Many tools and options I took for granted on *nix systems simply aren't available. For example, the ps command does recognize the --no-header or --user options.

Other annoyances: tar doesn't recognize the z modifier and the absolute worst: grep doesn't recognize -r. No recursive grep. The options are either doing a find and piping the results to grep or using ack (the latter of which is lovely, I might add).

Re:Fixing up that shell command

djberg96 on 2008-02-14T21:14:56

Many Solaris admins replace the default tar with GNU tar, perhaps installing it as gtar, giving users their choice.

Some admins get their panties in a bunch over the fact that GNU tar is not POSIX compliant, but most people shrug and decided they'd rather have something useful over some notion of correct, especially when Sun's tar can't handle paths over 256 characters.

That may be specifically relevent to you as a Catalyst user given this thread from comp.unix.solaris.

Re:Fixing up that shell command

steph on 2008-02-14T22:00:22

can't you simply install some packages? sunfreeware.com is a good place.

Anyway my point was: don't forget /proc and magic ps ;) perl -lpe 's{\0}{ }g' /proc/*/cmdline

cheers --stephan p.d at least if you have a decent support for it always worth to remember.

Why Sed?

Smylers on 2008-02-13T21:23:44

    # The sed bit is embarrassing but needed on a Cat restart
    # when the shell quotes things :/
    chomp(my @processes
      = uniq `ps -ef|grep "$user.*$app_name"|grep -v grep|sed -e 's/"//g' -e 's/.* script//'`
    );

Why use Sed at all? Won't it work to do the transformations on Perl list elements rather than on lines in the shell?

  chomp my @processes = uniq map { tr/"//d; s/.* script//; $_ }
    `ps -ef|grep "$user.*$app_name"|grep -v`;

Re:Why Sed?

djberg96 on 2008-02-13T21:59:54

Why use the shell at all? Shame on you both with your platform specific solutions.

See Proc::ProcessTable

Re:Why Sed?

vek on 2008-02-14T00:31:09

I wholeheartedly use and recommend Proc::ProcessTable. That is until I had to use it on an Opteron Solaris 10 box. I was in a hurry so I just said bugger it and scraped the output of ps instead.

Re:Why Sed?

djberg96 on 2008-02-14T15:53:28

There's a bug in Proc::ProcessTable, though I couldn't tell you what it is offhand. The sys-proctable library, which started as a port of Dan's work, picks up other processes just fine.

The only security change for /proc they made between 9 and 10 that I'm aware of is the cmdline information is now restricted to 80 characters unless you own the process. Which, in practice, meant we had to shell out to use /usr/ucb/ps -auxwww so we could distinguish between the Java processes with ridiculously long command strings.

hrm...

Alias on 2008-02-14T00:13:43

This is screaming out for something to be bundled with Cat, or for a Firefox plugin, or something...