📄 ntploopwatch
字号:
#!/local/bin/perl -w--*-perl-*-;#;# ntploopwatch,v 3.1 1993/07/06 01:09:13 jbj Exp;#;# process loop filter statistics file and either;# - show statistics periodically using gnuplot;# - or print a single plot;#;# Copyright (c) 1992 ;# Rainer Pruy Friedrich-Alexander Universitaet Erlangen-Nuernberg;#;#;#############################################################$0 =~ s!^.*/([^/]+)$!\1!;$F = ' ' x length($0);$|=1;$ENV{'SHELL'} = '/bin/sh'; # use bourne shellundef($config);undef($workdir);undef($PrintIt);undef($samples);undef($StartTime);undef($EndTime);($a,$b) if 0; # keep -w happy$usage = <<"E-O-P";usage: to watch statistics permanently: $0 [-v[<level>]] [-c <config-file>] [-d <working-dir>] $F [-h <hostname>] to get a single print out specify also $F -P[<printer>] [-s<samples>] $F [-S <start-time>] [-E <end-time>] $F [-Y <MaxOffs>] [-y <MinOffs>]If You like long option names, You can use: -help -c +config -d +directory -h +host -v +verbose[=<level>] -P +printer[=<printer>] -s +samples[=<samples>] -S +starttime -E +endtime -Y +maxy -y +minyIf <printer> contains a '/' (slash character) output is directed to a file of this name instead of delivered to a printer.E-O-P;# add directory to look for lr.pl and timelocal.pl (in front of current list)unshift(@INC,"/src/NTP/v3/xntp/monitoring");require "lr.pl"; # linear regresion routines$MJD_1970 = 40587; # from ntp.h (V3)$RecordSize = 48; # usually a line fits into 42 bytes$MinClip = 0.12; # clip Y scales with greater range than this;# largest extension of Y scale from mean value, factor for standart deviation$FuzzLow = 2; # for side closer to zero$FuzzBig = 1; # for side farther from zerorequire "ctime.pl";require "timelocal.pl";;# early distributions of ctime.pl had a bug$ENV{'TZ'} = 'MET' unless defined $ENV{'TZ'} || $[ > 4.010;if (defined(@ctime'MoY)){ *Month=*ctime'MoY; *Day=*ctime'DoW;}else{ @Month = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); @Day = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');};# max number of days per month@MaxNumDaysPerMonth = (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);;# config settable parameters$delay = 60;$srcprefix = "./var\@\$STATHOST/loopstats.";$showoffs = 1;$showfreq = 1;$showcmpl = 0;$showoreg = 0;$showfreg = 0;undef($timebase);undef($freqbase);undef($cmplscale);undef($MaxY);undef($MinY);$deltaT = 512; # indicate sample data gaps greater than $deltaT seconds$verbose = 1;while($_ = shift(@ARGV)){ (/^[+-]help$/) && die($usage); (/^-c$/ || /^\+config$/) && (@ARGV || die($usage), $config = shift(@ARGV), next); (/^-d$/ || /^\+directory$/) && (@ARGV || die($usage), $workdir = shift(@ARGV), next); (/^-h$/ || /^\+host$/) && (@ARGV || die($usage), $STATHOST = shift, next); (/^-v(\d*)$/ || /^\+verbose=?(\d*)$/) && ($verbose=($1 eq "") ? 1 : $1, next); (/^-P(\S*)$/ || /^\+[Pp]rinter=?(\S*)$/) && ($PrintIt = $1, $verbose==1 && ($verbose = 0), next); (/^-s(\d*)$/ || /^\+samples=?(\d*)$/) && (($samples = ($1 eq "") ? (shift || die($usage)): $1), next); (/^-S$/ || /^\+[Ss]tart[Tt]ime$/) && (@ARGV || die($usage), $StartTime=&date_time_spec2seconds(shift),next); (/^-E$/ || /^\+[Ee]nd[Tt]ime$/) && (@ARGV || die($usage), $EndTime = &date_time_spec2seconds(shift),next); (/^-Y$/ || /^\+[Mm]ax[Yy]$/) && (@ARGV || die($usage), $MaxY = shift, next); (/^-y$/ || /^\+[Mm]in[Yy]$/) && (@ARGV || die($usage), $MinY = shift, next); die("$0: unexpected argument \"$_\"\n$usage");}if (defined($workdir)){ chdir($workdir) || die("$0: failed to change working dir to \"$workdir\": $!\n");}$PrintIt = "ps" if defined($PrintIt) && $PrintIt eq "";if (!defined($PrintIt)){ defined($samples) && print "WARNING: your samples value may be shadowed by config file settings\n"; defined($StartTime) && print "WARNING: your StartTime value may be shadowed by config file settings\n"; defined($EndTime) && print "WARNING: your EndTime value may be shadowed by config file settings\n"; defined($MaxY) && print "WARNING: your MaxY value may be shadowed by config file settings\n"; defined($MinY) && print "WARNING: your MinY value may be shadowed by config file settings\n"; ;# check operating environment ;# ;# gnuplot usually has X support ;# I vaguely remember there was one with sunview support ;# ;# If Your plotcmd can display graphics using some other method ;# (Tek window,..) fix the following test ;# (or may be, just disable it) ;# !(defined($ENV{'DISPLAY'}) || defined($ENV{'WINDOW_PARENT'})) && die("Need window system to monitor statistics\n");};# configuration file$config = "loopwatch.config" unless defined($config);($STATHOST = $config) =~ s!.*loopwatch\.config.([^/\.]*)$!\1! unless defined($STATHOST);($STATTAG = $STATHOST) =~ s/^([^\.\*\s]+)\..*$/\1/;$srcprefix =~ s/\$STATHOST/$STATHOST/g;;# plot command @plotcmd=("gnuplot", '-title', "Ntp loop filter statistics $STATHOST", '-name', "NtpLoopWatch_$STATTAG");$tmpfile = "/tmp/ntpstat.$$";;# other variables$doplot = ""; # assembled command for @plotcmd to display plotundef($laststat);;# plot value rangesundef($mintime);undef($maxtime);undef($minoffs);undef($maxoffs);undef($minfreq);undef($maxfreq);undef($mincmpl);undef($maxcmpl);undef($miny);undef($maxy);;# stop operation if plot command diessub sigchld{ local($pid) = wait; unlink($tmpfile); warn(sprintf("%s: %s died: exit status: %d signal %d\n", $0, (defined($Plotpid) && $Plotpid == $pid) ? "plotcmd" : "unknown child $pid", $?>>8,$? & 0xff)) if $?; exit(1) if $? && defined($Plotpid) && $pid == $Plotpid;}&sigchld if 0;$SIG{'CHLD'} = "sigchld";$SIG{'CLD'} = "sigchld";sub abort{ unlink($tmpfile); defined($Plotpid) && kill('TERM',$Plotpid); die("$0: received signal SIG$_[$[] - exiting\n");}&abort if 0; # make -w happy - &abort IS used$SIG{'INT'} = $SIG{'HUP'} = $SIG{'QUIT'} = $SIG{'TERM'} = $SIG{'PIPE'} = "abort";;#sub abs{ ($_[$[] < 0) ? -($_[$[]) : $_[$[];};#####################;# start of real work print "starting plot command (" . join(" ",@plotcmd) . ")\n" if $verbose > 1;$Plotpid = open(PLOT,"|-");select((select(PLOT),$|=1)[$[]); # make PLOT line bufferddefined($Plotpid) || die("$0: failed to start plot command: $!\n");unless ($Plotpid){ ;# child == plot command close(STDOUT); open(STDOUT,">&STDERR") || die("$0: failed to redirect STDOUT of plot command: $!\n"); print STDOUT "plot command running as $$\n"; exec @plotcmd; die("$0: failed to exec (@plotcmd): $!\n"); exit(1); # in case ...}sub read_config{ local($at) = (stat($config))[$[+9]; local($_,$c,$v); (undef($laststat),(print("stat $config failed: $!\n")),return) if ! defined($at); return if (defined($laststat) && ($laststat == $at)); $laststat = $at; print "reading configuration from \"$config\"\n" if $verbose; open(CF,"<$config") || (warn("$0: failed to read \"$config\" - using old settings ($!)\n"), return); while(<CF>) { chop; s/^([^\#]*[^\#\s]?)\s*\#.*$//; next if /^\s*$/; s/^\s*([^=\s]*)\s*=\s*(.*\S)\s*$/\1=\2/; ($c,$v) = split(/=/,$_,2); print "processing \"$c=$v\"\n" if $verbose > 3; ($c eq "delay") && ($delay = $v,1) && next; ($c eq 'samples') && (!defined($PrintIt) || !defined($samples)) && ($samples = $v,1) && next; ($c eq 'srcprefix') && (($srcprefix=$v)=~s/\$STATHOST/$STATHOST/g,1) && next; ($c eq 'showoffs') && ($showoffs = ($v eq 'yes' || $v eq 'y' || $v != 0),1) && next; ($c eq 'showfreq') && ($showfreq = ($v eq 'yes' || $v eq 'y' || $v != 0),1) && next; ($c eq 'showcmpl') && ($showcmpl = ($v eq 'yes' || $v eq 'y' || $v != 0),1) && next; ($c eq 'showoreg') && ($showoreg = ($v eq 'yes' || $v eq 'y' || $v != 0),1) && next; ($c eq 'showfreg') && ($showfreg = ($v eq 'yes' || $v eq 'y' || $v != 0),1) && next; ($c eq 'exit') && (unlink($tmpfile),die("$0: exit by config request\n")); ($c eq 'freqbase' || $c eq 'cmplscale') && do { if (! defined($v) || $v eq "" || $v eq 'dynamic') { eval "undef(\$$c);"; } else { eval "\$$c = \$v;"; } next; }; ($c eq 'timebase') && do { if (! defined($v) || $v eq "" || $v eq "dynamic") { undef($timebase); } else { $timebase=&date_time_spec2seconds($v); } }; ($c eq 'EndTime') && do { next if defined($EndTime) && defined($PrintIt); if (! defined($v) || $v eq "" || $v eq "none") { undef($EndTime); } else { $EndTime=&date_time_spec2seconds($v); } }; ($c eq 'StartTime') && do { next if defined($StartTime) && defined($PrintIt); if (! defined($v) || $v eq "" || $v eq "none") { undef($StartTime); } else { $StartTime=&date_time_spec2seconds($v); } }; ($c eq 'MaxY') && do { next if defined($MaxY) && defined($PrintIt); if (! defined($v) || $v eq "" || $v eq "none") { undef($MaxY); } else { $MaxY=$v; } }; ($c eq 'MinY') && do { next if defined($MinY) && defined($PrintIt); if (! defined($v) || $v eq "" || $v eq "none") { undef($MinY); } else { $MinY=$v; } }; ($c eq 'deltaT') && do { if (!defined($v) || $v eq "") { undef($deltaT); } else { $deltaT = $v; } next; }; ($c eq 'verbose') && ! defined($PrintIt) && do { if (!defined($v) || $v == 0) { $verbose = 0; } else { $verbose = $v; } next; }; ;# otherwise: silently ignore unrecognized config line } close(CF); ;# set show defaults when nothing selected $showoffs = $showfreq = $showcmpl = 1 unless $showoffs || $showfreq || $showcmpl; if ($verbose > 3) { print "new configuration:\n"; print " delay\t= $delay\n"; print " samples\t= $samples\n"; print " srcprefix\t= $srcprefix\n"; print " showoffs\t= $showoffs\n"; print " showfreq\t= $showfreq\n"; print " showcmpl\t= $showcmpl\n"; print " showoreg\t= $showoreg\n"; print " showfreg\t= $showfreg\n"; printf " timebase\t= %s",defined($timebase)?&ctime($timebase):"dynamic\n"; printf " freqbase\t= %s\n",defined($freqbase) ?"$freqbase":"dynamic"; printf " cmplscale\t= %s\n",defined($cmplscale)?"$cmplscale":"dynamic"; printf " StartTime\t= %s",defined($StartTime)?&ctime($StartTime):"none\n"; printf " EndTime\t= %s", defined($EndTime) ? &ctime($EndTime):"none\n"; printf " MaxY\t= %s",defined($MaxY)? $MaxY :"none\n"; printf " MinY\t= %s",defined($MinY)? $MinY :"none\n"; print " verbose\t= $verbose\n"; }print "configuration file read\n" if $verbose > 2;}sub make_doplot{ local($c) = (""); local($fmt) = ("%s \"%s\" using 1:%d title '%s <%lf %lf> %6s' with lines"); local($regfmt) = ("%s ((%lf * x) + %lf) title 'lin. approx. %s (%f t[h]) %s %f <%f> %6s' with lines"); $doplot = " set title 'NTP loopfilter statistics for $STATHOST " . "(last $LastCnt samples from $srcprefix*)'\n"; local($xts,$xte,$i,$t); local($s,$c) = (""); ;# number of integral seconds to get at least 12 tic marks on x axis $t = int(($maxtime - $mintime) / 12 + 0.5); $t = 1 unless $t; # prevent $t to be zero foreach $i (30, 60,5*60,15*60,30*60, 60*60,2*60*60,6*60*60,12*60*60, 24*60*60,48*60*60) { last if $t < $i; $t = $t - ($t % $i); } print "time label resolution: $t seconds\n" if $verbose > 1; ;# make gnuplot use wall clock time labels instead of NTP seconds for ($c="", $i = $mintime - ($mintime % $t); $i <= $maxtime + $t; $i += $t, $c=",") { $s .= $c; ((int($i / $t) % 2) && ($s .= sprintf("'' %lf",($i - $LastTimeBase)/3600))) || (($t <= 60) && ($s .= sprintf("'%d:%02d:%02d' %lf", (localtime($i))[$[+2,$[+1,$[+0], ($i - $LastTimeBase)/3600))) || (($t <= 2*60*60) && ($s .= sprintf("'%d:%02d' %lf", (localtime($i))[$[+2,$[+1], ($i - $LastTimeBase)/3600))) || (($t <= 12*60*60) && ($s .= sprintf("'%s %d:00' %lf", $Day[(localtime($i))[$[+6]], (localtime($i))[$[+2], ($i - $LastTimeBase)/3600))) || ($s .= sprintf("'%d.%d-%d:00' %lf", (localtime($i))[$[+3,$[+4,$[+2], ($i - $LastTimeBase)/3600)); } $doplot .= "set xtics ($s)\n"; chop($xts = &ctime($mintime)); chop($xte = &ctime($maxtime)); $doplot .= "set xlabel 'Start: $xts -- Time Scale -- End: $xte'\n"; $doplot .= "set yrange [" ; $doplot .= defined($MinY) ? sprintf("%lf", $MinY) : $miny; $doplot .= ':'; $doplot .= defined($MaxY) ? sprintf("%lf", $MaxY) : $maxy; $doplot .= "]\n"; $doplot .= " plot"; $c = ""; $showoffs && ($doplot .= sprintf($fmt,$c,$tmpfile,2, "offset", $minoffs,$maxoffs, "[ms]"), $c = ","); $showcmpl && ($doplot .= sprintf($fmt,$c,$tmpfile,4, "compliance" . (&abs($LastCmplScale) > 1 ? " / $LastCmplScale" : (&abs($LastCmplScale) == 1 ? "" : " * ".(1/$LastCmplScale))), $mincmpl/$LastCmplScale,$maxcmpl/$LastCmplScale, ""), $c = ","); $showfreq && ($doplot .= sprintf($fmt,$c,$tmpfile,3, "frequency" . ($LastFreqBase > 0 ? " - $LastFreqBaseString" : ($LastFreqBase == 0 ? "" : " + $LastFreqBaseString")), $minfreq * $FreqScale - $LastFreqBase, $maxfreq * $FreqScale - $LastFreqBase, "[${FreqScaleInv}ppm]"), $c = ","); $showoreg && $showoffs && ($doplot .= sprintf($regfmt, $c, &lr_B('offs'),&lr_A('offs'), "offset ", &lr_B('offs'), ((&lr_A('offs')) < 0 ? '-' : '+'), &abs(&lr_A('offs')), &lr_r('offs'), "[ms]"), $c = ","); $showfreg && $showfreq && ($doplot .= sprintf($regfmt, $c, &lr_B('freq') * $FreqScale, (&lr_A('freq') + $minfreq) * $FreqScale - $LastFreqBase, "frequency", &lr_B('freq') * $FreqScale, ((&lr_A('freq') + $minfreq) * $FreqScale - $LastFreqBase) < 0 ? '-' : '+', &abs((&lr_A('freq') + $minfreq) * $FreqScale - $LastFreqBase), &lr_r('freq'), "[${FreqScaleInv}ppm]"), $c = ","); $doplot .= "\n";}%F_key = ();%F_name = ();%F_size = ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -