netsh
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:20k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. #!/usr/bin/perl
  2. use Getopt::Std;
  3. use DBI;
  4. use Term::ReadLine;
  5. use SNMP;
  6. use AutoLoader;
  7. use IO::File;
  8. BEGIN {
  9.     $opts{'t'} = ! eval { require Text::FormatTable; };
  10.     $ansicolor = eval { require Term::ANSIColor; };
  11. }
  12. # override some of the functions to force our colorized semantics.
  13. # This is really ugly, but if you pass colorized strings directly to
  14. # Text::FormatTable then it calculates the string lengths incorrectly.
  15. # Children: don't try this at home.  We're trained professionals.
  16. if ($colorize) {
  17.    eval {
  18.         #
  19. # colorized strings.
  20. #
  21. package color_string;
  22. require Term::ANSIColor;
  23. use overload
  24.     '""' => &string_it
  25. ;
  26. sub string_it {
  27.     if ($_[0][3]) {
  28. if ($_[0][3] == 1) {
  29.     return color_it();
  30. } else {
  31.     $_[0][3] -= 1;
  32.     return $_[0][1];
  33. }
  34.     }
  35.     return $_[0][1];
  36. }
  37.         sub colorize_next {
  38.     $_[0][3] = 2;
  39. }
  40. sub color_it {
  41.     my $str = $_[1] || $_[0][1];
  42.     return $_[0][0] . $str . $_[0][2];
  43. }
  44. sub new {
  45.     my $this = [Term::ANSIColor::color($_[2]), $_[1],
  46.       Term::ANSIColor::color('reset')];
  47.     return bless($this, $_[0]);
  48. }
  49.     }
  50. }
  51. if ($opts{'t'} == 0 && $colorize) {
  52.     eval {
  53. package Text::FormatTable;
  54. sub _l_box($$)
  55. {
  56.     my ($width, $text) = @_;
  57.     my $lines = _wrap($width, $text);
  58.     map { 
  59. if (ref($text) eq "color_string") {
  60.     $_ .= $text->color_it($_) . ' 'x($width-length($_));
  61. } else {
  62.     $_ .= ' 'x($width-length($_));
  63.     } @$lines;
  64.     return $lines;
  65. }
  66. sub _r_box($$)
  67. {
  68.     my ($width, $text) = @_;
  69.     my $lines = _wrap($width, $text);
  70.     map { 
  71. if (ref($text) eq "color_string") {
  72.     $_ = ' 'x($width-length($_)) . $text->color_it($_);
  73. } else {
  74.     $_ = ' 'x($width-length($_)) . $_;
  75.     } @$lines;
  76.     return $lines;
  77. }
  78.     }
  79. }
  80. if (!$ansicolor) {
  81.     $begin = $end = "*";
  82. }
  83. $SNMP::use_enums=1;
  84. #defaults
  85. $opts{'d'} = "t";
  86. $opts{'v'} = 1;
  87. $opts{'l'} = 'authNoPriv';
  88. $params = "";
  89. getopts('hd:tR:u:l:v:a:A:x:X:p:c:t:r:',%opts);
  90. usage() if ($#ARGV == -1 || $opts{'h'});
  91. my %parammap = {
  92.     'v' => 'Version',
  93.     'u' => 'SecName',
  94.     'a' => 'AuthProto',
  95.     'A' => 'AuthPass',
  96.     'x' => 'PrivProto',
  97.     'X' => 'PrivPass',
  98.     'p' => 'RemotePort',
  99.     't' => 'Timeout',
  100.     'r' => 'Retries',
  101.     'c' => 'Community',
  102.     'l' => 'SecLevel'
  103.     };
  104. foreach my $x (keys(%opts)) {
  105.     if ($parammap{$x}) {
  106. $params .= ";ad_SNMP_$parammap{$x}=$x";
  107.     }
  108.     push @sessparams,$parammap{$x},$x;
  109. }
  110. my $host = shift @ARGV;
  111. $params .= ";ad_SNMP_DestHost=" . $host;
  112. push @sessparms,'DestHost', $host;
  113. # connect to the DBI interface
  114. $AnyData::Storage::SNMP::debugre = $opts{'R'} if ($opts{'R'});
  115. ($dbh = DBI->connect("dbi:AnyData:ad_default=SNMP$params"))
  116.     || die "tConnection problem: $DBI::errstrn";
  117. $AnyData::Storage::SNMP::debugre = $opts{'R'} if ($opts{'R'});
  118. $prompt = "netsh> ";
  119. load_rcs();
  120. # setup terminal prompter
  121. $ENV{'PERL_RL'}='o=0' if (!exists($ENV{'PERL_RL'}));
  122. # the ornaments are too ugly
  123. $term = new Term::ReadLine 'netsh';
  124. if ($#ARGV >= 0) {
  125.     # command line command
  126.     netsh(join(" ",@ARGV));
  127. } else {
  128.     # interactive shell
  129.     while($cmd = $term->readline($prompt)) {
  130. last if ($cmd eq "exit" || $cmd eq "quit" || $cmd eq "q");
  131. netsh($cmd, %conf);
  132.     }
  133. }
  134. # load all configuration files we can find.
  135. sub load_rcs {
  136.     if (-f "$ENV{'HOME'}/.snmp/netshrc") {
  137. source_file("$ENV{'HOME'}/.snmp/netshrc");
  138.     }
  139.     if (-d "$ENV{'HOME'}/.snmp/netsh") {
  140. foreach my $i (glob("$ENV{'HOME'}/.snmp/netsh/*")) {
  141.     if (-f "$i" && "$i" !~ /.*(~|.bak)$/) {
  142. source_file("$i");
  143.     }
  144. }
  145.     }
  146. }
  147. # command definition for sourcing a particular file
  148. sub source_file {
  149.     my $fh = new IO::File;
  150.     if ($fh->open("<$_[0]")) {
  151. while(<$fh>) {
  152.     if (s/<<s*(w+)$//) {
  153. my $stopat = $1;
  154. my $lines = $_;
  155. while(<$fh>) {
  156.     last if (/$stopat/);
  157.     $lines .= $_;
  158. }
  159. $_ = $lines;
  160.     }
  161.     netsh($_);
  162. }
  163.     } else {
  164. print STDERR "no such file: $_[0]n";
  165.     }
  166. }
  167. # export data into an external file
  168. sub my_export {
  169.     shift;
  170.     if (!$insh) {
  171. my $cmd = "create table exporttable (" . join (" varchar(255), ",@{$sth->{NAME}}) . " varchar(255))";
  172. $exporth->do($cmd);
  173. $cmd = "insert into exporttable values(" . ('?, ' x ($#_)) . "?)";
  174. $insh = $exporth->prepare($cmd);
  175.     }
  176.     $insh->execute(@_);
  177. }
  178. # the main processing function.
  179. sub netsh {
  180.     my $stmt = shift;
  181.     chomp($stmt);      # remove trailing white space
  182.     $stmt =~ s/^s+//; # remove leading white space
  183.     $stmt =~ s/;*$//;  # get rid of trailing semicolons
  184.     return if ($stmt =~ /^s*$/);
  185.     return if ($stmt =~ /^s*#/);
  186.     my ($name, $args) = ($stmt =~ /^(w+)s*(.*)$/);
  187.     #define alias
  188. #    print "doing [$multi_alias]: $stmtn";
  189.     if ($name eq "alias" || $multi_alias) {
  190. if ($multi_alias) {
  191.     if ($stmt =~ /^prompts+(d+)s+["'](.+)["']/) {
  192. $aliases{$current_alias}{'prompts'}[$1] = $2;
  193. return;
  194.     } elsif ($stmt =~ /^prompts+(d+)s+(.+)/) {
  195. my $x = $2;
  196. my $spot = $1;
  197. $x =~ s/s+$//;
  198. $aliases{$current_alias}{'prompts'}[$spot] = "$x ";
  199. return;
  200.     } elsif ($stmt =~ /^s*}s*$/) {
  201. $prompt = $oprompt;
  202. $multi_alias = 0;
  203. return;
  204.     }
  205.     push @{$aliases{$current_alias}{'definition'}},$stmt;
  206.     return;
  207. }
  208. $stmt =~ s/^aliass+//;
  209. if ($args eq "") {
  210.     foreach $i (sort keys(%aliases)) {
  211. display_alias($i);
  212.     }
  213.     return;
  214. }
  215. ($name, $args) = ($stmt =~ /^(w+)s*(.*)$/);
  216. if ($args eq "") {
  217.     display_alias($name);
  218.     return;
  219. }
  220. # print "alias: $name $argsn";
  221. if ($args eq "{") {
  222.     $oprompt = $prompt;
  223.     $prompt = "define $name> ";
  224.     $current_alias = $name;
  225.     $multi_alias = 1;
  226.     $aliases{$name}{'definition'} = [];
  227.     return;
  228. }
  229. $aliases{$name}{'definition'} = $args;
  230. return;
  231.     }
  232.     #eval
  233.     if ($name eq "eval") {
  234. eval $args;
  235. return;
  236.     }
  237.     #eval just vars
  238.     if ($name eq "evalvars") {
  239. # print "args1:",$args,"n";
  240. $args =~ s/$(w+)/$$1/eg;
  241. # print "args2:",$args,"n";
  242. netsh($args);
  243. return;
  244.     }
  245.     #eval aliases
  246.     while (exists $aliases{$name}) {
  247. # print "modified: $stmt -> ";
  248. my @ARGS = split(/s+/,$args);
  249. my $statements;
  250. if (ref($aliases{$name}{'definition'}) eq "ARRAY") {
  251.     $statements = $aliases{$name}{'definition'};
  252.     # maybe prompt for values
  253.     if ($#{$aliases{$name}{'prompts'}} > -1) {
  254. my $i;
  255. for($i = 1; $i <= $#{$aliases{$name}{'prompts'}}; $i++) {
  256.     if (!$ARGS[$i-1] && $term) {
  257. $ARGS[$i-1] = 
  258.     $term->readline($aliases{$name}{'prompts'}[$i]);
  259.     }
  260. }
  261.     }
  262. } else {
  263.     $statements = [$aliases{$name}{'definition'}];
  264. }
  265. foreach my $stmt (@$statements) {
  266.     #print "$stmt -> ";
  267.     $stmt =~ s/\(d+)/$ARGS[$1-1]/g;
  268. #     print "running $stmtn";
  269.     ($name, $args) = ($stmt =~ /^(w+)s*(.*)$/);
  270.     netsh($stmt);
  271. }
  272. return;
  273.     }
  274.     if ($stmt =~ /^rehash$/) {
  275. load_rcs();
  276. return;
  277.     }
  278.     my $subfn;
  279.     if ($stmt =~ /^eval (.*)/) {
  280. eval $1;
  281.     }
  282.     if ($stmt =~ s/^printfs+(".*")s*(.*)/$2/) {
  283. if ($2 eq "") {
  284.     print eval $1;
  285.     return;
  286. }
  287. $subfn = &my_printf;
  288. $stmt = $2;
  289. $printfmt = $1;
  290.     }
  291.     # special show columns statement
  292.     if ($stmt =~ /^show columns from (w+)$/) {
  293. my $mibnode = $SNMP::MIB{$1};
  294. my $entrynode = $mibnode->{children}[0];
  295. if (!defined($mibnode) || !defined($entrynode)) {
  296.     print STDERR "no such table: $1n";
  297.     return;
  298. }
  299. if ($opts{'t'}) {
  300.     map { print $_->{label},"n"; } sort { $a->{subID} <=> $b->{subID}} @{$entrynode->{children}};
  301. } else {
  302.     $table = Text::FormatTable->new('|r|');
  303.     $table->rule('-');
  304.     $table->head('Column');
  305.     $table->rule('-');
  306.     map { $table->row($_->{label}); } sort { $a->{subID} <=> $b->{subID}} @{$entrynode->{children}};
  307.     $table->rule('-');
  308.     print $table->render();
  309. }
  310. return;
  311.     }
  312.     if ($stmt =~ /^sources+(.*)/) {
  313. source_file($1);
  314. return;
  315.     }
  316.     if ($stmt =~ s/^exports+(S+)s+(.*)/$2/) {
  317. $insh = undef;
  318. unlink($1);
  319. $exporth = DBI->connect('dbi:AnyData:');
  320. $exporth->func('exporttable','CSV',$1,'ad_catalog');
  321. $subfn = &my_export;
  322.     }
  323.     if ($stmt =~ /^imports+(S+)/) {
  324. my $exporth = DBI->connect('dbi:AnyData:');
  325. $exporth->func('exporttable','CSV',$1,'ad_catalog');
  326. my $selh = $exporth->prepare("select * from exporttable");
  327. $selh->execute();
  328. $old_data = [];
  329. while(my $row = $selh->fetchrow_arrayref) {
  330.     push @$old_data, @$row;
  331. }
  332. $selh->finish();
  333. $exporth->disconnect();
  334. return;
  335.     }
  336.     
  337.     if ($stmt =~ /^diffs+(.*)/) {
  338. $running_watch = 2;
  339. netsh($1);
  340. $running_watch = 0;
  341. return;
  342.     }
  343.     if ($stmt =~ /^watchs+(.*)/) {
  344. $running_watch = 1;
  345. my $cmd = $1;
  346. my $delay = 1;
  347. my $clear = `clear`;
  348. if ($cmd =~ s/^(d+)s+(.*)/$2/) {
  349.     $delay = $1;
  350.     $cmd = $2;
  351. }
  352. $SIG{'TERM'} = sub { $running_watch = 0; };
  353. $SIG{'INT'} = sub { $running_watch = 0; };
  354. while($running_watch) {
  355.     print $clear;
  356.     netsh($cmd);
  357.     sleep($delay);
  358. }
  359. $SIG{'TERM'} = &exit;
  360. $SIG{'INT'} = &exit;
  361. return;
  362.     }
  363.     # we have an SQL statement.  process it.
  364.     if ($stmt =~ /^(select|insert|update|delete)/) {
  365. $sth = $dbh->prepare($stmt);
  366. $sth->execute();
  367. if ($stmt =~ /^select/) {
  368.     my $table;
  369.     my $older_data = $old_data;
  370.     if ($running_watch == 1) {
  371. $old_data = [];
  372.     }
  373.     my $oldcount = 0;
  374.     while($row = $sth->fetchrow_arrayref) {
  375. if ($running_watch) {
  376.     $newrow=[];
  377.     my $count;
  378.     for($count = 0; $count <= $#$row; $count++) {
  379. if ($older_data &&
  380.     $row->[$count] ne
  381.     $older_data->[$oldcount][$count]) {
  382.     if ($ansicolor) {
  383. push @$newrow, new color_string($row->[$count],'red');
  384.     } else {
  385. push @$newrow,"$begin$row->[$count]$end";
  386.     }
  387. } else {
  388.     push @$newrow,$row->[$count];
  389. }
  390. if ($running_watch == 1) {
  391.     $old_data->[$oldcount][$count] = $row->[$count];
  392. }
  393.     }
  394.     $oldcount++;
  395.     $row = $newrow;
  396.   }
  397. # self printing;
  398. if (ref($subfn) eq "CODE") {
  399.     &$subfn($printfmt,@$row);
  400.     next;
  401. }
  402. if ($opts{'t'}) {
  403.     if ($opts{'d'} eq 'xml') {
  404. print "  <row>n";
  405. for(my $xx = 0; $xx < $#{$sth->{NAME}}; $xx++) {
  406.     print "    <$sth->{NAME}[$xx]>$row->[$xx]</$sth->{NAME}[$xx]>n";
  407. }
  408. print "  </row>n";
  409.     } elsif ($opts{'d'} eq 'xmlshort') {
  410. print "  <row ";
  411. for(my $xx = 0; $xx < $#{$sth->{NAME}}; $xx++) {
  412.     print " $sth->{NAME}[$xx]="$row->[$xx]"";
  413. }
  414. print "/>n";
  415.     } else {
  416. print join($opts{'d'},@$row),"n";
  417.     }
  418. } elsif (!$table) {
  419.     $table = Text::FormatTable->new('|r' x ($#$row+1) . "|");
  420.     $table->rule('-');
  421.     $table->head(@{$sth->{NAME}});
  422.     $table->rule('-');
  423.     $table->row(@$row);
  424. } else {
  425.     $table->row(@$row);
  426. }
  427.     }
  428.     if ($table) {
  429. $table->rule('-');
  430. print $table->render();
  431.     }
  432. }
  433. $sth->finish();
  434. return;
  435.     }
  436.     # retrieve just one variable and display it
  437.     if ($stmt =~ /^(get|)s*([^s]+)s*[^=]/) {
  438. my $sess = make_session();
  439. if ($sess) {
  440.     my @results = split(/[,s]+/,$stmt);
  441.     my $resultsv = new SNMP::VarList();
  442.     # expression stolen from the main perl SNMP module
  443.     map {  my ($tag, $iid) = 
  444.        (/^((?:.d+)+|(?:w+(?:-*w+)+)).?(.*)$/);
  445.    push @$resultsv, [$tag, $iid] } @results;
  446.     $sess->get($resultsv)  || 
  447. print STDERR "Error: $sess->{ErrorNum} $sess->{ErrString}n";
  448.        @results = ();
  449.     map { push @results, $_->[2] } @$resultsv;
  450.     if (ref($subfn) eq "CODE") {
  451. &$subfn($printfmt,@results);
  452.     } else {
  453. print join(" ", @results),"n";
  454.     }
  455. } else {
  456.     print STDERR "could not establish a SNMP session to $hostn";
  457. }
  458. return;
  459.     }
  460.     # set something
  461.     if ($stmt =~ /^(set|)s*([^s]+)s=s(.*)$/) {
  462. my $sess = make_session();
  463. if ($sess) {
  464.     $sess->set([$2,undef,$1]) || 
  465. print STDERR "opps: $sess->{ErrorNum} $sess->{ErrString}n";
  466. } else {
  467.     print STDERR "could not establish a SNMP session to $hostn";
  468. }
  469. return;
  470.     }
  471. }
  472. sub auto_snmp {
  473.     my $node = $SNMP::MIB{$_[0]};
  474. #    print STDERR "netsh::fetch_snmp $_[0] $node->{label}n";
  475.     my $indexes = $node->{parent}{indexes};
  476.     if ($#$indexes > -1) {
  477. # print STDERR "columnn";
  478. # table 
  479.     } else {
  480. # scalar
  481. if (exists($_[1])) {
  482.     my $sess = make_session();
  483.     my $val = $sess->set([$_[0],0,$_[1]]) || return;
  484. #     print STDERR "scalar set: $valn";
  485.     return $val;
  486. } else {
  487.     my $sess = make_session();
  488.     my $val = $sess->get([$_[0],0]);
  489. #     print STDERR "scalar get: $valn";
  490.     return $val;
  491. }
  492.     }
  493. }
  494. sub AUTOLOAD {
  495.     my $nodename = $AUTOLOAD;
  496.     $nodename =~ s/.*:://;
  497.     print STDERR "netsh::AUTOLOAD $AUTOLOAD $nodenamen";
  498.     if ($SNMP::MIB{$nodename}) {
  499. eval << "END";
  500.         sub $AUTOLOAD {
  501.     auto_snmp($nodename, @_);
  502. }
  503. END
  504. goto &$AUTOLOAD;
  505.     }
  506.     print STDERR join(",",@_),"n";
  507. }
  508. sub my_printf {
  509.     # drop quotes
  510.     my $fmt = shift;
  511.     $fmt = eval $fmt;
  512.     map { if (ref($_) eq "color_string") { $_->colorize_next(); } } @_;
  513.     printf($fmt, @_);
  514. }
  515. sub display_alias {
  516.     my $name = shift;
  517.     if (exists $aliases{$name}{'definition'}) {
  518. if (ref($aliases{$name}{'definition'}) eq "ARRAY") {
  519.     print "alias $name {n";
  520.     map { print "  $_n"; } @{$aliases{$name}{'definition'}};
  521.     print "}n";
  522. } else {
  523.     print "alias $name $aliases{$name}{'definition'}n";
  524. }
  525.     } else {
  526. print "no alias defined for "$name"n";
  527.     }
  528. }
  529. sub make_session {
  530.     if (!$sess) {
  531. $sess = new SNMP::Session(@sessparms);
  532.     }
  533.     return $sess;
  534. }
  535. sub usage {
  536.     print STDERR "
  537. $0 [ARGUMENTS] HOSTNAME [SQL_COMMAND] 
  538.   $0 implements a simple SQL shell which maps onto SNMP.  All
  539.   statements issued within the shell are converted to SNMP requests and
  540.   sent to HOSTNAME and the results displayed in a nice table output
  541.   format if the Text::FormatTable module is available.  If SQL_COMMAND
  542.   is given on the command line, then it's interpreted and control is
  543.   returned to the caller.  If not, an interactive prompt is given where
  544.   multiple commands can be issued.
  545. ARGUMENTS may include:
  546.   -t         delimiter separated output, don't print pretty tables.
  547.   -d DELIM   use DELIM as the delimiter.  A tab is the default delimiter.
  548.              'xml' is a special delimiter to produce xml output.
  549. ARGUMENTS also may include the following.  See the net-snmp snmpcmd
  550. manual page for details on what they mean:
  551.   -v VERSION        (default: 1)
  552.   -t TIMEOUT
  553.   -r RETRIES
  554.   -p PORT
  555.   -c COMMUNITY
  556.   -a AUTHPROTOCOL   (default: MD5)
  557.   -x PRIVPROTOCOL   (default: DES)
  558.   -A AUTHPASS
  559.   -X PRIVPASS
  560.   -l SECURITY_LEVEL (default: authNoPriv)
  561.   
  562. ";
  563.     exit;
  564. }
  565. __END__
  566. =head1 NAME
  567. netsh - A shell environment for interacting with networking devices
  568. =head1 SYNOPSIS
  569. netsh [(subset of) snmpcmd arguments] hostname[,hostname...] [command]
  570. =head1 OPTIONAL PERL MODULES
  571. There are some optional perl modules which make using the shell nicer
  572. in general.  These modules are:
  573.   Text::FormatTable
  574.   Term::ReadLine::Gnu or Term::ReadLine::Perl
  575.   Term::ANSIColor
  576. You can install these by running [as root]:
  577.   perl -MCPAN -e shell
  578.   cpan> install Text::FormatTable
  579.   ...
  580. It is B<strongly> recommend you at least install the Text::FormatTable
  581. module, and if you like command line editing one of the two extra
  582. Term::ReadLine modules (Gnu being the better of the two).
  583. =head1 DESCRIPTION
  584. The netsh script provides an interactive, console-like environment
  585. suitable for monitoring and manipulating data within networking
  586. devices.  The environment is highly extensible through command
  587. aliases and easy-to-use SQL-like queries.
  588. It is implemented on top of the SNMP protocol using the net-snmp
  589. package and perl.  See the snmpcmd and snmp.conf manual pages for
  590. details on configuring net-snmp for authentication information for
  591. the networking devices you wish to access.
  592. =head1 ABOUT THE EXAMLPES IN THIS DOCUMENT
  593. All the examples in this document are exact cut-n-pastes from the
  594. inside of the netsh shell.  This includes the "netsh> " prompt and
  595. possibly other prompts as well.
  596. =head1 COMMANDS
  597. The following is a list of the basic core commands supported by
  598. netsh.  Many default aliases are also supplied, some of which are
  599. listed in the next section.  At the command prompt type "alias" for
  600. a full list of all the aliases and their definitions.
  601. =over
  602. =item show columns from TABLE
  603. =item select ... 
  604. =item update ...
  605. =item insert ...
  606. =item delete ...
  607. netsh supports the standard sql-like language queries of snmp tables.
  608. These are implemented via the SQL::Statement parser, so any form of
  609. expression it accepts netsh will accept as well.
  610. Examples:
  611.   netsh> show columns from ifTable
  612.   +-----------------+
  613.   |           Column|
  614.   +-----------------+
  615.   |          ifIndex|
  616.   ...
  617.   netsh> select * from ifTable
  618.   ... [output not shown]
  619.   netsh> select tcpConnState, tcpConnRemotelAddress from tcpConnTable where tcpConnState = established
  620.   ... [output not shown]
  621.   netsh> update ifTable set ifAdminStatus = up where ifOperStatus = down
  622.   ... [output not shown]
  623. =item SNMPOBJECT
  624. Simple lists of objects may be given which will directly request or
  625. operate on those objects.  See printf below for controlling the
  626. formatting of results
  627. Examples:
  628.   netsh> sysContact.0, sysLocation.0
  629.   hardaker@somewhere.net my location
  630.   netsh> sysContact.0 = my new contact information
  631. =item alias my_command some other command
  632. or
  633. =back
  634. alias my_many_commands {
  635.   command1
  636.   command2
  637.   prompt NUMBER question
  638. }
  639. =over
  640. =item
  641. You can create aliases of your frequently used commands by aliasing
  642. them to an easy to remember name.  N parameters in the defined
  643. command will be replaced by the positional argument of options passed
  644. to the alias name.
  645. For multi-line defined aliases, optional prompts may be given to
  646. request information from the user when the NUMBERth argument is not
  647. given to the alias.  If it is not given, the prompt will be printed
  648. and the user will be asked to input a value for it.  This allows the
  649. easy definition of interactive commands.  The value will be inserted
  650. in alias parts containing N substitution requests.
  651.   netsh> alias interfaces select ifDescr from ifTable
  652.   netsh> interfaces
  653.   +-------+
  654.   |ifDescr|
  655.   +-------+
  656.   |     lo|
  657.   |   eth0|
  658.   +-------+
  659.   netsh> alias interface select ifDescr, ifSpeed from ifTable where ifDescr = '1'
  660.   netsh> interface eth0
  661.   +-------+--------+
  662.   |ifDescr| ifSpeed|
  663.   +-------+--------+
  664.   |   eth0|10000000|
  665.   +-------+--------+
  666. =item printf FORMATSTRING COMMAND
  667. Allows B<careful> formatting of results returned by the commands.
  668. Example:
  669.   netsh> alias interface {
  670.   define interface> printf "interface %s is running at %d Mb/sn" select ifDescr, ifSpeed from ifTable where ifDescr = '1'
  671.   define interface> prompt 1 Enter the interface to describe:
  672.   define interface> }
  673.   netsh> interface
  674.   Enter the interface to describe: eth0
  675.   interface eth0 is running at 10000000 Mb/s
  676. To list the definition of an already defined command, simply exclude
  677. the definition and netsh will report the definition to you:
  678.   netsh> alias interface
  679.   alias interface {
  680.     printf "interface %s is running at %d Mb/sn" select ifDescr, ifSpeed from ifTable where ifDescr = '1'
  681.     prompt 1 Enter the interface to describe:
  682.   }
  683. To list all the aliases defined in the system, just type "alias" by itself.
  684. =item watch [TIME] COMMAND
  685. Continually watches the results of the COMMAND being run, which is run
  686. every TIME seconds.  For select statements, it will attempt to mark
  687. the changing values from one screen to the next by surrounding them
  688. with "*"s or color (assuming you have the Term::ANSIColor perl module
  689. installed) for easy picking out on the screen.
  690. =item rehash
  691. Re-load the alias definitions files in the common directory, as
  692. well as those files found in $HOME/.snmp/netsh.
  693. =item source FILE
  694. loads definitons and commands from FILE into the running environment.
  695. =back
  696. =head1 FILES
  697. By default, netsh will source all the definition files it can find.
  698. It does this by first reading everything in
  699. /usr/local/share/snmp/netsh/* and then reading everything in
  700. $HOME/.snmp/netsh/*.  Everything contained in these files are
  701. commands, but most frequently they entirely consist of aliases
  702. definitions.
  703. =head1 AUTHOR
  704. bugs, comments, questions to net-snmp-users@lists.sourceforge.net
  705. =head1 Copyright
  706.      Copyright (c) 2002 Networks Associates Technology, Inc. All
  707.      rights reserved.  This program is free software; you can
  708.      redistribute it and/or modify it under the same terms as Perl
  709.      itself.
  710. =cut