Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
Hello Monks,

I have written a short script as a pretentiously named 'proof of concept' for a project I am working on.

The project's aims are to create a daemon that accepts data and commands through a tcp socket, processes/prioritizes them and drives the data and formatting to an LCD screen over an i2c connection. In addition the daemon will respond to signals such as HUP to cause a re-initialization of the lcd device and USR1 to load custom characters.

The test script shown here does not include any of the lcd communication or command processing as I have this working already and it is not relevant to the test script.

As I have never written a Perl script to create a daemon, or use sockets or that is event driven, I would appreciate comments on my approach and programming details

The test script, so far works as I want ... The program is daemonized, the pid is stored in a file and error output is directed to an error file. The script responds to HUP and USR1 signals and data sent from another machine on the network is received and processed by the io socket.

For the test, the outputs are sent to a log file.

The three events: i/o, HUP & USR1 are handled in anonymous subroutines, but the data received by the i/o socket is then passed to a main loop for further processing using a condition variable with ->send.

The ->recv is in the main loop, and according to the documentation for AnyEvent, this blocks the loop from running until a ->send occurs. Can I just keep the loop running so that I can do other things?.

I am not sure if the way I have structured this is appropriate and of course my 'y' solution to the 'x' problem may not be the best way to solve my issue.

The test script responds to the following series of external commands:

TestEvent.pl sudo kill -USR1 $(cat events.pid) SktClnt.pl Enter data to send: A.B.C sudo kill -HUP $(cat events.pid)

... with this in the events.log file

25-04-2020 18:03:46, Port: 55129 looping 0 25-04-2020 18:04:02, User 1 signal received 25-04-2020 18:04:11, Connection received from 192.168.0.153 Data: A.B.C loop data: A.B.C 25-04-2020 18:04:20, Hangup

Here is the script

#!/usr/bin/perl # EventsTest.pl # Version 1.0, 25 April 2020 use Sys::HostIP; use Daemon::Daemonize qw( :all ); use IO::Socket::INET; use Event; use AnyEvent; use Date::Calc qw( Today_and_Now ); use strict; use warnings; $|++; # ********************************************************** # # ************** Variables to be set by user *************** # # ********************************************************** # base path/name for log files (e.g. /home/anita2r/events.log) my $base = "/home/anita2R/events"; # port for socket connection my $port = 55129; # ********************************************************** # # ****************** Create log files etc. ***************** # # ********************************************************** # # Setup log, error and pid files my $error_log = "$base.err"; my $pid_file = "$base.pid"; my $msg_log = "$base.log"; # clear error and log files truncate $error_log, 0; truncate $msg_log, 0; # ********************************************************** # # ************* Create a communications socket ************* # # ********************************************************** # # create a socket and log port number my $hostip = Sys::HostIP->new; my $ip = $hostip->ip; # save port to log file my $DtTm = DtTmStmp(); open( my $fh, '>>', $msg_log ); print $fh "$DtTm, Port: $port\n"; close $fh; # setup socket my $skt = IO::Socket::INET->new( Listen => 1, LocalAddr => $ip, LocalPort => $port, Proto => 'tcp', Reuse => 1, ) or die "$! ... Can't open socket on port $port\n"; # ********************************************************** # # ******************** Signal handlers ********************* # # ********************************************************** # # ********************************************************** # # HUP signal handler # for this test HUP will log and close the script my $wtforhup = AnyEvent->signal( signal => "HUP", cb => sub { my $DtTm = DtTmStmp(); open( my $fh, '>>', $msg_log ); print $fh "$DtTm, Hangup\n"; close $fh; # clear the pid file and stop the daemon delete_pidfile( $pid_file ); exit 1; } ); # ********************************************************** # # USR1 signal handler # for this test USR1 will just add an entry to the log my $wtforusr1 = AnyEvent->signal( signal => "USR1", cb => sub{ my $DtTm = DtTmStmp(); open( my $fh, '>>', $msg_log ); print $fh "$DtTm, User 1 signal received\n"; close $fh; } ); # ********************************************************** # # IO socket handler # read data, log receive # and pass it on for additional processing my $data; my $iocv = AnyEvent->condvar; my $wtforio = AnyEvent->io( fh => \*$skt, poll => 'r', cb => sub{ my $lskt = $skt->accept(); while( <$lskt> ) { $data = $_; chomp $data; my $hostip = $lskt->peerhost(); # log received data my $DtTm = DtTmStmp(); open( my $fh, '>>', $msg_log ); print $fh "$DtTm, Connection received from $hostip\n"; print $fh "Data: $data\n"; close $fh; } close( $lskt ); # send data for further processing # $iocv->recv is in main loop $iocv->send( $data ); } ); # ********************************************************** # # *********************** Daemonize ************************ # # ********************************************************** # # daemonize, redirect errors & save new pid daemonize( close => 'std', stderr => $error_log, ); write_pidfile( $pid_file ); # ********************************************************** # # ********************* Initialization ********************* # # ********************************************************** # # In the real program, various initialization routines # are carried out before entering the main program loop # ********************************************************** # # ******************* Main Program Loop ******************** # # ********************************************************** # my $loop = 1; my $a = 0; while( $loop ) { # just to show whether the loop is running # one entry every 5 seconds if( $a % 5 == 0) { open( $fh, '>>', $msg_log ); print $fh "looping $a\n"; close $fh; } $a++; sleep 1; # $iocv-recv blocks until an $iorecv->send my $data = $iocv->recv; open( $fh, '>>', $msg_log ); print $fh "loop data: $data\n"; close $fh; # done with this cv undef $iocv; # setup a fresh cv - loop will be blocked until next send $iocv = AnyEvent->condvar; } exit 0; # ********************************************************** # # ****************** General subroutines ******************* # # ********************************************************** # # ********************************************************** # # date/time stamp sub DtTmStmp { my( $yr, $mo, $dy, $hr, $mi, $se ) = Today_and_Now(); my $DtTm = sprintf( "%02d-%02d-%04d %02d:%02d:%02d", $dy, $mo, $yr, $hr, $mi, $se ); return $DtTm; } # ********************************************************** #

Regards

anita2R


In reply to AnyEvents - mainly by anita2R

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (7)
As of 2024-04-19 10:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found