Click to See Complete Forum and Search --> : For someone who knows perl AND php


Sweede
01-21-2001, 02:23 PM
i need to convert these functions/script into PHP for my control panel,
anyone care to help ??


#!/usr/bin/perl

$file = shift;

$chunksize = 5;
$monthsworth = 30 * 24 * (60 / $chunksize); # number of intervals in a month
$chunkseconds = $chunksize * 60;
$maxdeviation = .10 * $chunkseconds;
$warndeviation = .05 * $chunkseconds;
$day = 24 * 60 * 60 + $maxdeviation;

open(FILE, "<$file")
or die "Cannot open $file for reading: $!";
@logfile = <FILE>;
close(FILE);

@snapshots = &extractsnapshots(@logfile);
undef @logfile;
@snapshots = &trimsnapshots(@snapshots); # return only valid part of array
$chunklocation = int($#snapshots * .95);

$GBpM = int(($snapshots[$chunklocation] * $day * 30) / (1024 * 1024 * 1024));

print qq^95th percentile:
$snapshots[$chunklocation] bytes per second
$GBpM gigabytes per month
^;

sub extractsnapshots {
local(@logfile, @snapshots, $time, $incoming, $outgoing, $reftime) = @_;
for ($i = 0; $i < $#logfile - 1; $i++) {
($time, $incoming, $outgoing) =
$logfile[$i] =~ /^(\d+)\s+(\d+)\s+(\d+)/;
length($outgoing)
| | die "$0: corrupted logfile $ARGV[0]\n";
(($reftime) = $logfile[$i + 1] =~ /^(\d+)/) | |
die "$0: corrupted logfile $ARGV[0] (\$reftime)\n";
$time -= $reftime;
die "$0: time period more than a day\n" if $time > $day;
push(@snapshots, &splitinterval($time, $incoming + $outgoing));
last if $#snapshots >= $monthsworth * 2;
}
@snapshots;
}

sub splitinterval { # split anything up into 5-minute chunks
local(@_) = @_; # localize the arg array
if (&deviation($_[0]) >= $maxdeviation) {
warn "$0: splitinterval: dropping oddsized chunk $_[0] secs of $_[1] Bps\n";
shift(@_); shift(@_); return @_;
}
warn "$0: splitinterval: warning: oddsized chunk $_[0] secs of $_[1] Bps\n"
if &deviation($_[0]) >= $warndeviation;
return @_ if $_[0] < $chunkseconds + $maxdeviation;
$_[0] -= $chunkseconds;
return &splitinterval(@_, $chunkseconds, $_[1]);
}

sub deviation { # how far a number strays from multiple of $chunkseconds
local($seconds) = shift(@_);
$seconds < $chunkseconds && return $chunkseconds - $seconds;
$seconds %= $chunkseconds; # get modulus
$seconds > ($chunkseconds / 2) && return $chunkseconds - $seconds;
$seconds;
}

sub trimsnapshots {
local(@snapshots) = @_;
$#snapshots = $monthsworth * 2 - 1; # set size of array
# now drop trailing zeroes, in case it's a partial month
while (($snapshots > 1) && ($snapshots[$#snapshots] == 0)) {
pop(@snapshots); pop(@snapshots);
}
# now get rid of the times, leaving only the Bps averages per chunk...
local(@clean, $i);
for($i = 0; $i <= $#snapshots; $i++) {
push (@clean, $snapshots[$i]) if $i % 2; # only the odd-numbered cells
}
sort by_number @clean;
}

sub by_number { # for sorting from lowest to highest
$a <=> $b;
}

sub average { # average out a numeric array
local(@array) = @_; local($size) = $#array + 1;
local($sum);
foreach (@array) {
$sum += $_;
}
$sum / $size;
}



I could probably manage this myself, but there are a few things thaat confuse me.
particuarly the sub name { subroutines.
whats local ? the $#snapshots, @_ ,
sort by_number @clean;
i assume means sorty the array clean by number ?

This script parses standard MRTG log files and returns the 95% bandwidth measurements (stupid host provider bandwidth billing ideals)

here's an example of the log in case anyone needs it (first 50 lines, there is 2536 lines per log file)

980100901 14908198 124573322
980100901 0 0 0 0
980100602 0 0 0 0
980100600 0 0 0 0
980100300 0 1 75 160
980100000 75 160 307 459
980099700 305 457 307 459
980099400 0 0 0 0
980099100 0 0 13 12
980098800 12 11 13 12
980098500 5 64 1515 19223
980098200 1510 19158 1515 19223
980097900 17 18 18 19
980097600 0 0 0 0
980097300 0 0 0 0
980097000 0 0 0 0
980096700 0 0 0 0
980096400 0 0 0 0
980096100 0 0 13 12
980095800 12 11 13 12
980095500 0 0 0 0
980095200 0 0 0 0
980094900 0 0 0 0
980094600 0 0 0 0
980094300 0 0 0 0
980094000 0 0 0 0
980093700 0 0 0 0
980093400 0 0 12 12
980093100 11 11 12 12
980092800 0 0 0 0
980092500 0 0 0 0
980092200 0 0 0 0
980091900 0 0 0 0
980091600 0 0 0 0
980091300 0 0 0 0
980091000 3 40 516 6053
980090700 512 6012 516 6053
980090400 0 0 12 12
980090100 11 11 12 12
980089800 0 4 37 722
980089500 36 719 37 722
980089200 0 0 0 0
980088900 0 0 0 0
980088600 0 0 0 0
980088300 0 0 0 0
980088000 0 0 0 0
980087700 0 0 12 12
980087400 12 14 37 725
980087100 37 725 37 727
980086800 36 722 37 727


thanks

YaRness
01-21-2001, 03:32 PM
<PHP>
call perlscript
</PHP>

http://www.linuxnewbie.org/ubb/biggrin.gif j/k

i loooked at php a couple times, prolly wouldn't be too hard a thing to do with a little effort. i'm kinda in the middle of cleaning the apartment this afternoon though.

------------------
"Assembly of Japanese bicycle require great peace of mind."
Registered Linux User #188285 http://counter.li.org/

Sweede
01-21-2001, 04:32 PM
sample of output

root:>#./gen95.pl /home/sweede/public_html/mrtg/underthemain.net.log
./gen95.pl: splitinterval: dropping oddsized chunk 0 secs of 166903557 Bps
./gen95.pl: splitinterval: dropping oddsized chunk 1 secs of 8051 Bps
95th percentile:
0 bytes per second
0 gigabytes per month
[Virtual-Support]-[/home/sweede/bin]


now, i need to figure out how its calculating the bandwidth and whatnot, if the code is write or wrong above, and how to return that into a usable format i can shove into my php control panel.

plus if i can understand whats going on, there MUST be a faster way than opening a 45kilobyte file and looping through the file 2535 times. (the end value of $i in the
extractsnapshots sub)

TheLinuxDuck
01-21-2001, 05:09 PM
Originally posted by Sweede:
I could probably manage this myself, but there are a few things thaat confuse me.
particuarly the sub name { subroutines. whats local ? the $#snapshots, @_ , sort by_number @clean; i assume means sorty the array clean by number ?

What is it about the subroutines that confuses you? How they work or passing parameters or what?

Local is for variable declaration when you want to use a global variables name (that already exist, such as command line parameters in @ARGV) inside a sub (or code block) and keep it's previous data intact.

For example:

#!/usr/bin/perl -w
use strict;
#
# print CL params, then go into the sub to
# add to them, then reprint and exit
#
print "main: @ARGV\n";
ourFunction();
print "main: @ARGV\n";
exit;
#
# ourFunction prints the @ARGV, creates new data,
# then reprints before exiting
#
sub ourFunction
{
print "ourFunction: @ARGV\n";
print "ourFunction: Setting \@ARGV as local\n";
local (@ARGV);
print "ourFunction: adding items to \@ARGV\n";
push @ARGV, "Amore","Bof","Cthe","Dsame","Estuff";
print "ourFunction: @ARGV\n";
}

when run:

/home/root/perl/sweede> ./local.pl item1 item2 arg3 arg4
main: item1 item2 arg3 arg4
ourFunction: item1 item2 arg3 arg4
ourFunction: Setting @ARGV as local
ourFunction: adding items to @ARGV
ourFunction: Amore Bof Cthe Dsame Estuff
main: item1 item2 arg3 arg4


Does that make sense?

@snapshots is an array declared and defined by the return value of the sub extractsnapshots. The # when used with an array indicates the last slice of the array. It's an easy way to determine the size of the array. So, if @snapshots has 10 items, $#snapshots would return 9 (since slices start at 0, not 1).

@_ is a default perl array that subs use for passing command lines into the sub.

Let's say you called the sub mySub as:

mySub("/etc/passwd",14,"Jim Gordan");


Inside the sub mySub, the array @_ will contain the items passed into the function. And since array slices are retrieved by using a $ and a slice number, we see that the following are true, inside mySub:

$_[0]="/etc/passwd";
$_[1]=14;
$_[2]="Jim Gordan";

Or, another way to use these passed values inside a sub would be to assign their data to a scalar inside the sub as:

sub mySub
{
my($passwdFile,$userCount,$userName)=@_;
}


That assigns the values of @_ to the listed scalars, in order they were passed to the function.

As for sort by_number @clean, you are correct. If you did sort @clean without calling the by_number sub, your array would be sorted by ascii value (if I'm not mistaken) instead of by numbers. The by_numbers sub just uses the <=> operator, which compares two numbers, and gives a return value based on the comparison (0 if equals, 1 if 1st variable is greater, -1 if 2nd variable is greater).

This code could be cleaned up quite a bit. Why do you want to use PHP? IMHO perl works just as well.. I don't see any distinct advantages to use it. But, then again, I don't know it either. http://www.linuxnewbie.org/ubb/wink.gif

Just my opinions, etc, take them for what they're worth. http://www.linuxnewbie.org/ubb/smile.gif

------------------
TheLinuxDuck
I have a belly button.
:wq

Sweede
01-21-2001, 06:06 PM
that right there made more sense than the past hour in the #perl room , bunch of bastards they are.

i think the problem is half not knowing perl and all of its funky keywords, tricks and variable schemes ($" ,$\, $_, %,@ etc), and yea, this is slopped together isnt it ??

I want to intergrate it into my php based control panel, causs i understand php a whole hell of a lot better than perl.

but so far, this script doesnt really seem to be working at all.

if you know C , picking up php should be simple, or thats what ive been told.



#!/usr/bin/perl -w
use strict;
#
# print CL params, then go into the sub to
# add to them, then reprint and exit
#
print "main: @ARGV\n";
ourFunction();
print "main: @ARGV\n";
exit;
#
# ourFunction prints the @ARGV, creates new data,
# then reprints before exiting
#
sub ourFunction{
print "ourFunction: @ARGV\n";
print "ourFunction: Setting \@ARGV as local\n";
local (@ARGV);
print "ourFunction: adding items to \@ARGV\n";
push @ARGV, "Amore","Bof","Cthe","Dsame","Estuff";
print "ourFunction: @ARGV\n";
}


If i comment out the local (@ARGV);

it returns

root:>#./foo.pl one two three four
main: one two three four
ourFunction: one two three four
ourFunction: Setting @ARGV as local
ourFunction: adding items to @ARGV
ourFunction: one two three four Amore Bof Cthe Dsame Estuff
main: one two three four Amore Bof Cthe Dsame Estuff

this would be because @ARGV has a global scope yes ?

in php, this operates the opposite. all variables are explicitly local unless set global. Also, the following variables ALWAYS have a global scope (these are arrays)
$HTTP_SERVER_VARS
$HTTP_ENV_VARS
$HTTP_COOKIE_VARS
$HTTP_POST_VARS
$HTTP_GET_VARS
$HTTP_SESSION_VARS
$GLOBALS <- contains every variable in the script regardless of scope, including itself.

ENV_VARS and SESSION_VARS only exist in PHP 4.

if you want to see improper usage of PHPs variables, download phpnuke (www.phpnuke.org), and stroll through the code http://www.linuxnewbie.org/ubb/smile.gif


but, please dont take that as how php works, becuase its not. in fact, the guy that wrote it broke Rasmus's scope design.

good php code would be like the mantis project or phpslash project.

[This message has been edited by Sweede (edited 21 January 2001).]

[This message has been edited by Sweede (edited 21 January 2001).]

jemfinch
01-21-2001, 07:17 PM
#perl on openprojects.net is far better than any channel you'll find on efnet, if that's where you were.

And swing by any of the 4-6 channels I hang out at an say hi, if you want! http://www.linuxnewbie.org/ubb/smile.gif

Jeremy

Sweede
01-21-2001, 07:21 PM
thats where i was, im always on openprojects.net in #myphportal and #titanium

none there even bothered to look at the code and help re-work it to where you could at least undersatnd whats going on.

linuxducks examples helped a lot better than any discussion could of.

TheLinuxDuck
01-21-2001, 08:34 PM
Originally posted by Sweede:
that right there made more sense than the past hour in the #perl room , bunch of bastards they are.{/b]

LOL! I'm glad to help make it a clearer to you.. http://www.linuxnewbie.org/ubb/smile.gif Everyone in the programming forum is always willing to offer aide and help when we can.. it usually requires the topic in question to have some basis in what we already know.. http://www.linuxnewbie.org/ubb/smile.gif

[b]i think the problem is half not knowing perl and all of its funky keywords, tricks and variable schemes ($" ,$\, $_, %,@ etc),

Once you get used to it, it's rather handy, because when you look at a variable, you know right away what it is. But, everyone prefers different languages for different reasons. http://www.linuxnewbie.org/ubb/smile.gif

and yea, this is slopped together isnt it ??

Please don't think I am belittling the code.. I don't know who wrote it, and it's not horrible, IMO.. I just see some ways the code could be written cleaner, only because of the help and aide I have received through LNO. http://www.linuxnewbie.org/ubb/smile.gif

this would be because @ARGV has a global scope yes ?[/b

Yep! http://www.linuxnewbie.org/ubb/smile.gif

[b]in php, this operates the opposite. all variables are explicitly local unless set global.

Perl is sorta that way, except you have globals that are predefined (such as @ARGV), and you have global lexical variables, which are defined outside of any block in the source, and you have variables with are local to specific blocks of code, that cannot be accessed outside their block:
#!/usr/bin/perl -w
use strict;
#
# Two globals that can be access anywhere in
# this script
#
my($globalOne,$globalTwo);
#
# We'll create a new block of code, that only
# is entered if the user passes at least 2
# command line parameters into the script
#
if($#ARGV>0) {
#
# These two locals are declared inside this
# block of code, meaning that they can only
# be accessed in this block (and any block
# explicitly included within this block)
#
my($localOne,$localTwo);
#
# We'll assign the first two items of the
# command line to $localOne, and $localTwo
#
($localOne,$localTwo)=@ARGV;
#
# This next nested block of code will hold
# two more variables that can only be used
# within this block.
#
{
my($nestedOne,$nestedTwo);
#
# nestedOne and Two will hold copied of
# localOne and Two. Then, nestedOne and
# Two will be changed. Every A will be
# changed to a Z, and the globalOne and
# Two will contain the number of A's
# changed in each.
#
$nestedOne=$localOne;
$nestedTwo=$localTwo;
$globalOne=($nestedOne=~ tr/aA/zZ/);
$globalTwo=($nestedTwo=~ tr/aA/zZ/);
print "\$nestedOne: $nestedOne\n".
"\$nestedTwo: $nestedTwo\n";
}
# print "$nestedOne\n$nestedTwo\n";
#
# ^^ will fail outside of the block
#
print "\$localOne: $localOne\n".
"\$localTwo: $localTwo\n";
}
else {
print "Usage: $0 item1 item2\n";
}
#
# The only way that globalOne and Two will
# contain data is if the used passed command
# line parameters. We make sure that the
# variables are not undefined before attemping
# to print them
#
print "\$globalOne: $globalOne\n" if($globalOne);
print "\$globalTwo: $globalTwo\n" if($globalTwo);


I'm sure that you already have a pretty good idea of how scoping works, since you know C and php, but I just wanted to try and give you some more understanding into perl. http://www.linuxnewbie.org/ubb/smile.gif

I hope this helps out! http://www.linuxnewbie.org/ubb/smile.gif
Was there anything else that you were looking to understand better?

------------------
TheLinuxDuck
I have a belly button.
:wq