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

I am trying to convert a BASH script to perl as it is getting too complicated to manage in bash. The script is basically a menu to choose one of seven snmp commands to run against one of 761 remote elements in the network segment I am responsible for. The problem I have is that on of the snmpget command strings will "hang" during the communication proccess with any given elements. THe snmpget command places the N.E. (network element) into an administrative state of "inTest" which is returned to "enabled" upon sucessfull completion. If the proccess hangs with the script I have now, I have to ^C and choose the snmpset command to reenable this NE. in bash, I have used \trap 're-enable' 2\ to send the script to the re-enable procedure on ^C. This will only work once then any subsiquent ^C only interrupt the script echoing "^C" to the tty and I have to exit and rerun the script. I want to be able to monitor the output and if there is no output from the command on line #4 (all data is tee'd to a NE specific logfile overwritten when the procedure is executed) after 10 seconds then the script will return either to the main-menu procedure, or go straight to the re-enable procedure. Unfortunatly most of the script contains propriatary information and I can not put the actual bash script here due to the IP and NonDisclose I signed. in a nut shell I use:
#!/usr/bin/bash re-enable () { commands here to re-enable the NE echo -n "Press ENTER to continue" ; read a main-menu } check-NE () { trap 're-enable' 2 command series that hangs echo -n "Press ENTER to continue" ; read a main-menu } main-menu () { choices with read a case $a 1) re-enable;; 2) check-NE;; .. 8 case statements *) exit;; } main-menu
I am a perl neophite and can hardly get hello world to work right =) but I can fudge through everything except the monitor output, if no output in 10 seconds auto sigint and return to script sub-procedure. any help / advice is appreciated.

Replies are listed 'Best First'.
Re: Help with SIGINT
by Velaki (Chaplain) on Oct 31, 2004 at 14:36 UTC

    It sounds more like you're looking for an alarm to go off after ten seconds, which will stop the subprocess. One way this can be done is by setting up an alarm handler to stop the current subprocess, and return control to the main routine for rerunning, error message, etc.

    #!/usr/bin/perl use strict; use warnings; local $| = 1; # Our alarm handler: simply quits the # process, or eval block. $SIG{ALRM} = sub { die "our alarm went off\n" }; # Put it all in an eval block, so we # can regain control after if finishes # or dies. eval { #alarm(10); # set for ten seconds [example] alarm(1); # set for one second [example] print "Running subprocess, etc..."; sleep(5); # the sleep() merely simulates a running process print "done\n"; }; # Let's see if an error, from die, was # returned; and if it was, whether it # was because our alarm went off. if($@) { print "Timed out\n" if $@ =~ /our alarm went off/; # Do whatever else we wish. }

    You can always wrap a while around the thing, so you can keep calling the subprocess.

    Hope this helped,
    -v
    "Perl. There is no substitute."
Re: Help with SIGINT
by Anonymous Monk on Oct 31, 2004 at 20:04 UTC
    you're going about this in the wrong way. there's no need for any SIGINT magic (most likely). you just need to modify the timeout/repeat-count for the snmpset.
    $ snmpset -r 1 -t 1 -c $COMM $host $oid $type $val
    the above will try only once and wait only one second for the reply. there are equvalent settings for the Perl SNMP modules. i've only seen this in commands that tweak the interface config like 10/100/full/half/auto settings (reply lost during negotiation), change of IP address, and when sending a 'reboot' command.
    # something like this $rc = $sess->set( [ $oid, $type, $val ], { retries => 1, timeout => 1 +} ); if ( $rc != OK ) { if ( $rc != TIMEOUT ) { # some real error happened, do something } else { # probably worked but we got no response like we expected } } else { # wow, it worked and we got a response... }