PERL

[ introduction | Examples ]


Introduction


Example:
  1. The perl script to read the RSSI value and calcluate BER in Linux.
  2. The perl script to use Libaray and SNMP example.
  3. Example of  Getopts and database query (same power script)
  4. Example of using GetOpt::Long


Example 1:
#!/usr/bin/perl



#para 1: test time
#para 2 : enable traffic control or not, 1-enalbe, 0-disable
#para 3: file to save rssi value



if ( $#ARGV < 2)
{
print "You must give/supply 3 parameters\n";
}
$time_tick = $ARGV[0] * 3;
#print $time_tick
#1 second = 90 mini-tick = 1.1~1.5s

$total_rssi=0;
$total_retry=0;
$total_ack=0;

open (IN1, "cat /proc/driver/aironet/eth1/Stats |grep RetryLong |");
while ()
{
#parse the statistics info
($name, $prev_retry) = split;
}

open (IN2, "cat /proc/driver/aironet/eth1/Stats |grep RxAck |");
while ()
{
($nam, $prev_ack) = split;
}

#$prev_retry=`cat /proc/driver/aironet/eth1/Stats |grep RetryLong |awk '{print $2}'`
#$prev_ack=`cat /proc/driver/aironet/eth1/Stats |grep RxAck |awk '{print $2}'`

$prev_pl=0;


for ($i=0; $i<$time_tick ; $i++)
{

$per_rssi=0;

for ($j=0;$j<30;$j++)
{

open (IN3, "cat /proc/driver/aironet/eth1/Status |grep Strength |");
while ()
{
($nam, $rssi_cur) = split;
}
#$rssi_cur=`cat /proc/driver/aironet/eth1/Status |grep Strength |awk '{print $3}'`


$per_rssi+= $rssi_cur;
# sleep 0.01s
}
$total_rssi+=$per_rssi;
$per_rssi/=30;



open (IN4, "cat /proc/driver/aironet/eth1/Stats |grep RetryLong |");
while ()
{
#parse the statistics info
($name, $cur_retry) = split;
}

open (IN5, "cat /proc/driver/aironet/eth1/Stats |grep RxAck |");
while ()
{
($nam, $cur_ack) = split;
}
print ("$cur_retry, $cur_ack \n");

#$cur_retry=`cat /proc/driver/aironet/eth1/Stats |grep RetryLong |awk '{print $2}'`

$per_retry=$cur_retry - $prev_retry;
$prev_retry=$cur_retry;

# $cur_ack=`cat /proc/driver/aironet/eth1/Stats |grep RxAck |awk '{print $2}'`
$per_ack= $cur_ack - $prev_ack;
$prev_ack=$cur_ack;


$total_retry += $per_retry;
$total_ack += $per_ack;

if ($per_ack == 0 )
{
$pl_value=$prev_pl;
}
else
{
$pl_value=100*$per_retry/($per_ack+$per_retry);
}

$prev_pl=$pl_value;

$rnd_rs = int $per_rssi;
print ("round is $rnd_rs \n");
open(IN6, "grep -w $rnd_rs rtp |");
wh)
{
($rss, $rs_index, $per_index)=split;
}

#$rs_index=`grep -w $per_rssi rtp | awk '{print $2}'`

#new discrimination rule
if ( $pl_value > 50 )
{
$c=10;
# ((c=$rs_index*(100-$pl_value)*(100-$pl_value)/10000))
}
else
{
$c=$rs_index*(100-$pl_value)/100;
}

#change c to a string...?
$c_rate=$c."kbit";

print ("rate is $c_rate \n");

if ( $argv[1] == 1)
{

system("tc qdisc del dev eth1 root");
# echo "$per_rssi $pl_value $c_rate" >> $3
system("tc qdisc add dev eth1 root handle 1: cbq avpkt 1024 bandwidth 11mbit ");

system(" tc class add dev eth1 parent 1: classid 1:1 cbq rate $c_rate allot 1500 prio 1 bounded isolated");

system ("tc filter add dev eth1 parent 1: protocol ip prio 16 u32 match ip dst 10.0.0.1 flowid 1:1");

}


}

$avg_rssi=$total_rssi/$time_tick/30;
print "average rssi is $avg_rssi \n";
if ( $2 == 1 )
{
system("tc qdisc del dev eth1 root");
}


¡¡



Example 2:

#!/usr/bin/perl -w

package snmpit_ds72;

$| = 1; # Turn off line buffering on output

use SNMP;
use strict;

sub new($$;$) {

# The next two lines are some voodoo taken from perltoot(1)
my $proto = shift;
my $class = ref($proto) || $proto;

my $devicename = shift;
my $debug = shift;

if (!defined($debug)) {
$debug = 0;
}

if ($debug) {
print "snmpit_ds72 module initializing... debug level $debug\n";
}

$SNMP::debugging = ($debug - 5) if $debug > 5;
my $mibpath = "/usr/local/share/snmp/mibs";
&SNMP::addMibDirs($mibpath);
&SNMP::addMibFiles("$mibpath/RFC1155-SMI.txt",
"$mibpath/baytechf101a.mib.txt");

$SNMP::save_descriptions = 1; # must be set prior to mib initialization
SNMP::initMib(); # parses default list of Mib modules
$SNMP::use_enums = 1; #use enum values instead of only ints
print "Opening SNMP session to $devicename...\n" if $debug;
my $sess =new SNMP::Session(DestHost => $devicename, Community => 'public');
if (!defined($sess)) {
warn("ERROR: Unable to connect to $devicename via SNMP\n");
return undef;
}
print "Opening SNMP session successfully \n";
my $self = {};
$self->{SESS} = $sess;
$self->{DEBUG} = $debug;
$self->{DEVICENAME} = $devicename;

bless($self,$class);
return $self;
}

sub readmodnum {
my $modnum = " ";
my $self = shift;
my $OID = ".1.3.6.1.4.1.4779.1.1.3";
$modnum = $self->{SESS}->get([$OID,0]);
print "Number is $modnum via SNMP\n";
return 0;

}
sub writemodname {

my $self = shift;
my $OID = ".1.3.6.1.4.1.4779.1.1.3";
return 0;

}

sub readdhcpconfig {
my $modnum = 2;
my $self = shift;
my $OID = ".1.3.6.1.4.1.4779.1.2.2";
$modnum = $self->{SESS}->get([$OID,0]);
print "DHCP is $modnum via SNMP\n";
return 0;

}
sub dhcpenable {

my $CtOID = ".1.3.6.1.4.1.4779.1.2.2";
my $self = shift;
my $retval = $self->{SESS}->set([[$CtOID,"enabled","INTEGER"]]);
print "DHCP is enabled ,return value is $retval \n";
return 1;
}


sub power {
my $self = shift;
my $op = shift;
#my @ports = @_;

my $CtlOID = ".1.3.6.1.4.1.4779.1.3.5.4";
if ($op eq "on") { $op = "1 1.2"; }
elsif ($op eq "off") { $op = "0 1.2"; }
elsif ($op =~ /cyc/) { $op = "2 1.2";}

my $errors = 0;

$self->UpdateField($CtlOID,$op);
#foreach my $port (@ports) {
# print STDERR "**** Controlling port $port\n" if ($self->{DEBUG} > 1);
# if ($self->UpdateField($CtlOID,$port,$op)) {
# print STDERR "Outlet #$port control failed.\n";
# $errors++;
#}
#}

return $errors;
}

sub UpdateField {
my ($self,$OID,$val) = @_;

print "sess=$self->{SESS} $OID $val\n" if $self->{DEBUG} >= 1;
my $Status = 0;
my $retval;

$retval = $self->{SESS}->set([[$OID,0,"0 1.2","OCTETSTR"]]);

return 1;

}

# End with true
1;

#!/usr/bin/perl -wT

use snmpit_ds72;
use libtestbed;
use strict;
use English;
use Getopt::Std;

my $verbose = 1;
my $op = "off";
my $IP = "10.0.0.252";
my $device = new snmpit_ds72($IP,$verbose);
if (!defined $device) {
warn "Unable to contact controller . Skipping...\n";
next;
} else {
print "Calling device->power($op)\n"
if $verbose > 1;
$device->readmodnum();
$device->writemodname();
$device->readdhcpconfig();
#$device->dhcpenable();
$device->power($op);
}



Example 3:

#!/usr/bin/perl -wT

#
# Testbed Power Control script
#
# power [on|off|cycle] <node> [<node>] ...
#
############################################################

#
# Configure variables
#
use lib "/usr/testbed/lib";
use libdb;
use power_rpc27;
use snmpit_ds72;
use libtestbed;
use strict;
use English;
use Getopt::Std; #this line is necessary for "getopts" function. see Perl getopts Howto
#define usage() function
sub usage() {
print << "END";
Usage: $0 [-v n] [-e] <on|off|cycle> <node ...>
-e Surpress sending of event - for use by scripts that have already sent it
-v n Run with verbosity level n
END
1;
}

#
# Un-taint path since this gets called from setuid scripts.
#
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin:/usr/testbed/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

my $op = ""; #stores operation (on/off/cyc)
my @machines = (); #stores machines to operate on
my $ip = ""; #stores IP of a power controller
my $outlet = 0; #stores number of an outlet
my %IPList = (); #holds machine/ip pairs
my %OutletList = (); #holds machine/outlet pairs
my $exitval = 0;

#
# Process command-line arguments
#
my %opt = ();
getopts("v:he",\%opt); # the first parameter is a string for all options, second parameter is a hash

if ($opt{h}) {
exit &usage; # "h" for help, execute usage
}

# useful values are 0, 1, 2 and 3
my $verbose = 0;
if ($opt{v}) {
$verbose = $opt{v}; # opt{v} will return the values of verbose, that's why we need a colon in the opt string
}
print "VERBOSE ON: Set to level $verbose\n" if $verbose;

my $sendevent = 1;
if ($opt{e}) {
$sendevent = 0;
}

#
# Must have at least an op and a machine, so at least 2 ARGV
#
if (@ARGV < 2) {
exit &usage;
}


#
# Read in ARGV
#
$op = shift (@ARGV);
if ($op =~ /^(on|off|cycle)$/) {
$op = $1;
} else {
exit &usage;
}

#
# Untaint the arguments.
#
@machines = @ARGV; # parse the values of machine to be powered
foreach my $n (0..$#ARGV) {
$machines[$n] =~ s/^([-\@\w.]+)$/$1/;

# Shark hack
if ($machines[$n] =~ /^(sh\d+)-[1-8]$/) {
print "WARNING: Rebooting $machines[$n] will reboot all of shelf $1!\n";
$machines[$n] = $1;
}
# End shark hack
}

#
# Lowercase nodenames and remove duplicates
#
my %all_nodes = ();
foreach my $n (0..$#machines) {
$all_nodes{"\L$machines[$n]"} = 1; # Lowercase it and use as hash key
}
@machines= sort keys %all_nodes;

#
# Dump the args
#
print "do \"$op\" to @machines\n" if $verbose > 1;



#
# Get table of users <--> machines for those nodes, to make sure
# user is authorized to control the nodes
#

my %timelimited = ();

#
# Though TBNodeAccessCheck can check all nodes at once, we do it one at
# a time, so that we can get a list of all nodes we have access to. This
# is primarily to preserve the pre-libification behavior of power
#
my %outlets = ();
foreach my $node (@machines) {
if (!(($UID == 0) || TBNodeAccessCheck($UID,TB_NODEACCESS_POWERCYCLE,$node))) {
warn "You are not authorized to control $node. Skipping...\n";
next;
}

my $result = DBQueryFatal("select o.power_id, o.outlet, " .
"(CURRENT_TIMESTAMP - power_time > last_power) " .
"from outlets as o left join nodes as n on " .
"(o.node_id = n.node_id) ".
# Shark hack
"or (n.node_id = concat(o.node_id,'-1')) " .
# End shark hack
"left join node_types as t on n.type=t.type ".
"where o.node_id='$node'");
if ($result->num_rows() == 0) {
warn "No outlets table entry found for $node. Skipping...\n";
next;
}

my ($power_id, $outlet, $time_ok) = $result->fetchrow();

#
# Check for rate-limiting, and update the last power cycle time
# if it's been long enough. Root gets to bypass the checks, and
# we only update the timestamp if it is being turned on or cycled,
# to allow off then on without waiting (unless the on is too close
# to a previos on/cycle command)
#
if ( $op ne "off" ) {
if (! ($time_ok || ($UID == 0)) ) {
warn "$node was power cycled recently. Skipping...\n";
next;
} else {
DBQueryFatal("update outlets set last_power=CURRENT_TIMESTAMP " .
"where node_id = '$node'");
}
}

#
# Associate this node with the power controller it is attached to
#
push @{$outlets{$power_id}}, [$node, $outlet];
}

print "machines= ",join(" ",@machines),"\n" if $verbose;
print "devices= ", join(" ",keys %outlets),"\n" if $verbose;

foreach my $power_id (keys %outlets) {

#
# Get the list of outlet numbers used on this power controller
#
my @outlets = ();
my @nodes = ();
foreach my $node (@{$outlets{$power_id}}) {
my ($node_id, $outlet) = @$node;
push @outlets, $outlet;
push @nodes, $node_id;

}
my $nodestr = join(",",@nodes);

#
# Find out some information about this power controller
#
my $result = DBQueryFatal("select n.type, i.IP ".
"from nodes as n left join interfaces as i on n.node_id=i.node_id " .
"where n.node_id='$power_id'");
if ($result->num_rows() == 0) {
warn "No entry found for power controller $power_id. Skipping " .
"$nodestr\n";
$exitval++;
next;
}
my ($type, $IP) = $result->fetchrow();

#
# Finally, we look at the controller type and construct the proper type
# of object
#
my $errors = 0;
#the codes handling a snmp-controlled power device
if ($type eq "DS72-RPC14") {
my $device = new snmpit_ds72($IP,$verbose);
if (!defined $device) {
warn "Unable to contact controller for $nodestr. Skipping...\n";
next;
} else {
print "Calling device->power($op,@outlets)\n"
if $verbose > 1;
if ($device->power($op,@outlets)) {
print "Control of $nodestr failed.\n";
$errors++;
}
}
} elsif ($type eq "RPC27") {
if (rpc27ctrl($op,$power_id,@outlets)) {
print "Control of $nodestr failed.\n"; $exitval++;
}
} else {
print "power: Unknown power type '$type'\n";
$errors++;
}

if (!$errors) {
foreach my $node (@nodes) {
print "$node now ",($op eq "cycle" ? "rebooting" : $op),"\n";
if ($sendevent) {
my $state = TBDB_NODESTATE_SHUTDOWN;
TBSetNodeEventState($node,$state);
}
}
} else {
$exitval += $errors;
}

}

# Return 0 on success. Return non-zero number of nodes that failed.
exit $exitval;


Example of getopt():

  my $len = 0;
GetOptions ('length=i' => \$len); # will store in $len

Using =i in the above statement, means the option must be an integer. Other possible types are "=s", "=f"

#!/usr/bin/perl
use Getopt::Long;
GetOptions("o"=>\$oflag,
"verbose!"=>\$verboseornoverbose,
"string=s"=>\$stringmandatory,
"optional:s",\$optionalstring,
"int=i"=> \$mandatoryinteger,
"optint:i"=> \$optionalinteger,
"float=f"=> \$mandatoryfloat,
"optfloat:f"=> \$optionalfloat);
print "oflag $oflag\n" if $oflag;
print "verboseornoverbose $verboseornoverbose\n" if $verboseornoverbose;
print "stringmandatory $stringmandatory\n" if $stringmandatory;
print "optionalstring $optionalstring\n" if $optionalstring;
print "mandatoryinteger $mandatoryinteger\n" if $mandatoryinteger;
print "optionalinteger $optionalinteger\n" if $optionalinteger;
print "mandatoryfloat $mandatoryfloat\n" if $mandatoryfloat;
print "optionalfloat $optionalfloat\n" if $optionalfloat;

print "Unprocessed by Getopt::Long\n" if $ARGV[0];
foreach (@ARGV) {
print "$_\n";
}