Commit 40b46a3f authored by Duncan White's avatar Duncan White
Browse files

first version..

parents
The need came up to run a particular performance gathering
command on a server as root, but record the output somewhere
else.
Sounds like a very simple client/server. So here I've adapted
the pre-existing raspberry-pi-phonehome listener daemon to be a
command-listener. The command is a variable inside the script
of course.
In addition, I wrote a very simple cat-client that connects to
a server (like telnet) and grabs the output..
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use IO::Socket;
my $host = shift @ARGV || "146.169.22.26"; # shell4..
my $port = shift @ARGV || 55001;
#
# my $socket = connect_server();
# connect to our server (trying several times if
# necessary), return the socket we receive.
# In case of repeated failure, return undef.
#
sub connect_server()
{
warn "trying to connect to $host:$port\n";
foreach (1..5) {
my $socket = new IO::Socket::INET('PeerAddr' => $host,
'PeerPort' => $port,
'Proto' => 'tcp');
return $socket if $socket;
warn "trying again...\n";
sleep 1;
}
return undef;
}
my $socket = connect_server();
die "can't connect to $host:$port\n" unless $socket;
warn "connected to $host..\n";
while( <$socket> )
{
print;
}
#!/usr/bin/perl
#
# command-listener: daemon that listens for a connection on a
# port and runs a single specific command, sending the
# results of running that command back to the client.
#
use strict;
use warnings;
use Data::Dumper;
use IO::Socket;
use POSIX 'WNOHANG';
use csglib::Log;
# important constants
# think about logging later..
my $logfile = "/tmp/command-listener.log";
# command to run..
my $command = "/bin/date"; # example:-)
my $port = shift @ARGV || 55001;
my $quit = 0;
my $log = new csglib::Log( scriptname=>"command-listener",
file=>$logfile,
level=>LOG_INFO ) ||
die "command-listener: can't create $logfile\n";
#
# my $socket = initialize_listener( $port );
# start listening server on port $port..
# return the socket we receive. In case of
# total failure, return undef.
#
sub initialize_listener ($)
{
my( $port ) = @_;
# signal handler for child die events
$SIG{CHLD} = sub { while( waitpid(-1,WNOHANG)>0 ) {} };
# signal handle for being interrupted
$SIG{INT} = sub { $quit++ };
$log->info( "trying to listen on port $port" );
foreach (1..5) {
my $socket = new IO::Socket::INET(
'LocalPort' => $port,
'Listen' => 20,
'Proto' => 'tcp',
'Reuse' => 1,
'Timeout' => 3600 );
return $socket if $socket;
$log->info( "trying again..." );
sleep 1;
}
return undef;
}
#
# connection_loop( $listensocket, $callback );
# take the listening socket $listensocket
# and a callback function $callback.
# forever wait for connections, forking
# a child for each connection, and making
# the child call the callback function $callback
# to handle one conversation with one client.
#
sub connection_loop ($$)
{
my( $listensocket, $callback ) = @_;
while( !$quit )
{
next unless my $conn = $listensocket->accept;
defined( my $child = fork()) ||
$log->fatal( "can't fork: $!" );
if( $child == 0 ) # child
{
$listensocket->close;
my $peer = getpeername($conn);
my($port, $iaddr) = sockaddr_in($peer);
my $peerhostname = gethostbyaddr($iaddr, AF_INET);
my $peeraddr = inet_ntoa($iaddr);
$log->info( "accepted connection from $peeraddr, host $peerhostname" );
STDIN->fdopen($conn,'<') ||
$log->fatal( "can't reopen STDIN: $!" );
STDOUT->fdopen($conn,'>') ||
$log->fatal( "can't reopen STDOUT: $!" );
#STDERR->fdopen($conn,'>') ||
# $log->fatal( "can't reopen STDERR: $!" );
$| = 1; # auto flush
$callback->();
exit 0;
}
$conn->close;
}
}
#
# converse();
# handle one client<->server conversation,
# there's no from-client data needed (if there was,
# it would be on STDIN), simply run $command which
# will produce output on STDOUT, which will be
# automatically sent back to the client.
#
sub converse ()
{
system( $command );
}
# stage 1: initialize the listener
my $socket = initialize_listener( $port );
$log->fatal( "can't create listening socket $port" ) unless $socket;
# stage 2: connection loop
$log->warn( "server listening on port $port, ready for connections" );
connection_loop( $socket, \&converse );
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment