Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

RPC

by jeffa (Bishop)
on Nov 08, 2000 at 00:30 UTC ( [id://40418]=perlquestion: print w/replies, xml ) Need Help??

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

I am working on a system monitoring agent. A server program will run in the background on the machine to be monitored and will listen to requests from clients on a specified port. Once it receives a request, it will return the output of the requested command (df, top, etc) to the client.

In my search I decided to use the Msg.pm and RPC.pm modules written by Sriram Srinivasan in his Advanced Perl Programming book (chpt 13).

My question is: has anybody in the monastary used these modules and does anybody know of any issues associated with them?

So far so good - they _seem_ to be working for me like a charm. But I have a suspicious feeling that there might be something else out there that might offer a better solution. Plus, if anybody has any tips, I would appreciate them as well.

Thanks,
Jeff

Replies are listed 'Best First'.
Re: RPC
by lhoward (Vicar) on Nov 08, 2000 at 00:46 UTC
    I feel bad giving you a non-perl answer, but why not just use an SNMP agent (like the free UCDavis SNMP agent)? It is already designed to do what you want (take in network requests and return status info; it has an extension to run programs and return the results). SNMP is a well-documented, RFC'd protocol designed to do this kind of stuff. There are already perl modules that implement SNMP (so you can easily do your client bit in perl). Using what is already built will probably save you a lot of time and effort.
      Good answer, but the boss man wants to use TCP/IP - SNMP is right out. Most of the time and effort I spend on this is helping me understand networking in general - so I don't mind - at least not yet! ;)
RE (tilly) 1: RPC
by tilly (Archbishop) on Nov 08, 2000 at 06:34 UTC
    Well a natural RPC protocol to use is called http. Really. I would suggest a simple CGI script for this task. That is a well-known protocol. Perl is able to be the client, or you can view what you want from any machine using a regular old browser...
      Yeah, I gotta one up this. jeffa and I chatted about this on the phone (welcome to Louisville, Jeff =) and I pointed out that he was lucky merlyn was infiltrating the Java types. Normally we leave it to him to shout HTTP eq instant_solution in these cases.

      To add to what tilly is saying here when you are simply invoking a process on a remote box with real simple arguements or none at all why throw IPC and the like at the problem? And as he said, the benefit of HTTP is that you can use all kinds of handy toys with it. And most, if you want a slightly more strict data-markup, throw XML::Simple into the mix.

      --
      $you = new YOU;
      honk() if $you->love(perl)

      Thanks for the input tilly and extremely - I totally agree, and at some point I will probably drop this RPC solution and use HTTP. I think the boss-man wanted to give me a project to help me understand how networking and sockets work in general, while at the same time helping me to understand how our servers are set up (and get on the good side of the sysadmins).
Re: RPC
by reyjrar (Hermit) on Nov 08, 2000 at 03:47 UTC
    oh yeah, and be careful.. make sure your script has an array of commands its allowed to run, that way no one can cat /etc/passwd through your script or something like that. if you're going to need to cehck files on the system.. it might pay to setup an array of those files, that way no one can access anything you don't want them to see via your script. ie:
    my @CMDS = ("ps", "top", "df", "vmstat", "blah"); my @FILES = ( "/etc/running.cfg", "/home/me/lastchecked.txt", "/var/l +og/httpd/error_log"); my ($cmd, @ARGS) = split(/\s/, $input); my $ok; for(@CMDS) { if($cmd eq $_) { $ok=1; } } if(!$ok) { die "tried to do something that wasn't cool: $input\n"; } # then check for files in args my $ok=0; my $arg; foreach $arg (@ARGS) if(-e $arg) { # we have a file $file=true; for(@FILES) { if($arg eq $_) { $ok=1; } } } } if($file && !$ok) { die "tried to access a bad thing: $input\n"; } # We're pretty much safe to continue

    untested, but you get the idea.. make sure that only what you anticipate being input is actually input, that way you can pretty much secure the script.. also run it as a user with as little privileges as possible..

    -brad
      Done and done!

      I went overboard on this issue. The server has a config file that it reads the actual *nix commands from, along with a pneumonic name (i.e. inodes='df -i') and stores the key-value pairs in a hash. When a client connects to the server, the server sends the pneumonics, so the client never sees the actual command.

      # from server sub get_commands() { open CONF, 'query.conf' or die "No config file found: $!\n"; while (<CONF>) { next if /^#/; chomp; my ($command, $query) = split(/\t/, $_); $commands{$command} = $query; } close CONF; } sub send_commands { my $rhost = shift; my @commands = sort keys %commands; &log_msg("Request for command list from $rhost"); return join(":", @commands); } # and from the client sub get_commands { my $answer; my $i = 'a'; eval { $answer = $conn->rpc('send_commands', $host) }; die "Server $rhost not responding\n" if $@; map { $commands{$i++} = $_ } split(":", $answer); } sub print_menu { print '#' x 30, "\n"; map { print "# $_) $commands{$_}\n" } sort keys %commands; print "# q) quit\n"; print '#' x 30, "\n"; print "Enter choice: "; } # the main processing loop for the client $SIG{ALRM} = sub { die "TIMEOUT" }; &print_menu; while (my $arg = <>) { last if $arg =~ /q/; chomp $arg; my $answer; eval { alarm(10); $answer = $conn->rpc('run', $commands{$arg}, $host) }; alarm(0); }; warn "$queries{$arg} timed out - $host could be down\n" if $@ =~ / +TIMEOUT/; print $answer; &print_menu; }
      Of course the major limitation at this point is only 'a' thru 'p' commands will be available.
RE: RPC
by geektron (Curate) on Nov 08, 2000 at 02:22 UTC
    i'd actually opt for IPC::Open2 or IPC::Open3.

    errors in the process running remotely are captured w/ Open3.

    i'd also suggest SNMP, but if that's not an option. . .

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://40418]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (7)
As of 2024-04-25 08:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found