in reply to POE::Wheel questions

Normally, most programs that allow reload of configurations have a SIGHUP signal handler (or SIGUSR1) which causes the reload. The reason for this is simple: you don't want to reload an incomplete file - if the sysadmin is in the middle of saving when you notice the file changed, you could interrupt the save process, read half a file, and get something that didn't make sense. Or maybe the sysadmin was saving progress as they went because they were worried about losing changes - e.g., working via dial-up, and worried that their connection would drop at any minute now that their teenaged daughter just got home from school and would mindlessly pick up the phone to call her friends who she just left not more then 20 minutes ago at school, but had to call them right now! In that case, you don't want to pick up the changes until the user explicitly told you to. And the popular way, as I said, is to run "kill 1 `cat /var/pid/yourprogram.pid`". Or something to similar effect. (1 is SIGHUP on most systems.)

Efficient means you need to keep the filehandle open - opening for append on each line can get expensive for large files. More efficient may be to log to a database and let the database handle the conflicts.

Final question: yes - you could telnet in via Net::Telnet and do whatever you want with the incoming data.

Replies are listed 'Best First'.
Re^2: POE::Wheel questions
by shockers (Acolyte) on Oct 03, 2005 at 18:41 UTC
    Great advice on questions 1 and 3, Tanktalus.

    I'll look into signals for my first problem (seeing when the configuration file finished being changed).

    For the 3rd problem, the remote system is out of my control: I telnet to it without a userid/password and I'm in. The remote system (running VxWorks) offers few commands and immediately dumps stuff, I presume, to stderr. So I was going to use $telnet->getline, but I can't get past $telnet->login because that statement requires username and password.

    On the 2nd question, my app is a middleman ... I let people define what logfiles (and search string and optional run-if-match command) to look for and then I generate a single new logfile that must be in a specific format. Another existing app will look at my new logfile and it can grab that data at any time and rotate it out (rename it) into a backup file. That's the reason I'm doing the inefficient open/write/close each time. So I'm not sure how I can use a database since I'm not privy to the app reading my output logfile. I had hoped opening in append mode would not lock it so the other app could grab it, but alas that didn't work. One other less efficient choice is a system call to cat to append things.

    UPDATE ON Net::Telnet

    Played some more and discovered that the Net::Telnet->new() made the connection to the id-less/psw-less system and I didn't need to do a $telnet->login. Since the remote system is forever dumping data (as far as I was concerned), I planned to looped forever:

    my $line; while ($line = $telnet->getline) { print $line; }
    But since it dumps data at different times, I ran into a "read timed-out" problem. Is there a way to disable the timeout? Setting to 0 didn't work, so I set it to a high value (one day):
    my $line; while ( $line = $telnet->getline(Timeout=>86400000) ) { print $line; }

      Log file: Sorry, I don't have any suggestions if you can't control your consumers. In that case, there's no point in calling the system 'cat' command - it will just do the same thing: open the file in append (well, the shell will do that), which automatically seeks to the end, write out, and close the filehandle. That would be even more inefficient.

      Mind you, if the rotation happens before the files get too large, the inefficiencies will be reduced. Each time you open a file and seek to the end, you won't seek very far, which will limit the ugliness. Note that it may still be an O(n) operation to seek to the end, but we're keeping n from getting too large.

      As for your timeout, I don't see any way to disable it. Better, then, may be simply to handle it by retrying. Set the errmode to 'return', and test to see if getline returns undef. Check the timed_out method to see if the undef is because of a timeout (then redo) or not (then last to end the loop - you're disconnected, most likely).

      $telnet->errmode('return'); while (my $line = $telnet->getline(Timeout => 3600)) { if (not defined $line and $telnet->timed_out()) { # print LOGFILE "It's been an hour since the last text... still wa +iting.\n"; redo; } print $line; }

      Hope that helps,

        Yes, your suggestions are a great help.

        Way back when you suggested SIGHUP to check for a change to a configuration file, I found a nice example at the end of a perl.active-venture.com article.

        And your example for the $telnet->getline timeout is good. I know I need to handle a bad network connection or remote system getting rebooted. And I also need to handle my own system getting rebooted, which should be taken care of by making my script a daemon that automatically gets restarted.

        Thanks.