BSD-Sysctl

 view release on metacpan or  search on metacpan

Sysctl.pm  view on Meta::CPAN

    return $self;
}

XSLoader::load 'BSD::Sysctl', $VERSION;

=head1 NAME

BSD::Sysctl - Manipulate kernel sysctl variables on BSD-like systems

=head1 VERSION

This document describes version 0.11 of BSD::Sysctl, released
2014-01-22.

=head1 SYNOPSIS

  use BSD::Sysctl 'sysctl';

  # exact values will vary
  print sysctl('kern.lastpid'); # 20621

  my $loadavg = sysctl('vm.loadavg');
  print $loadavg->[1]; # 0.6127 (5 minute load average)

  my $vm = sysctl('vm.vmtotal');
  print "number of free pages: $vm->{pagefree}\n";

=head1 DESCRIPTION

C<BSD::Sysctl> offers a native Perl interface for fetching sysctl
values that describe the kernel state of BSD-like operating systems.
This is around 80 times faster than scraping the output of the
C<sysctl(8)> program.

This module handles the conversion of symbolic sysctl variable names
to the internal numeric format, and this information, along with
the details of how to format the results, are cached. Hence, the
first call to C<sysctl> requires three system calls, however,
subsequent calls require only one call.

=head1 ROUTINES

=over 4

=item sysctl

Perform a sysctl system call. Takes the symbolic name of a sysctl
variable name, for instance C<kern.maxfilesperproc>, C<net.inet.ip.ttl>.
In most circumstances, a scalar is returned (in the event that the
variable has a single value).

In some circumstances a reference to an array is returned, when the
variable represents a list of values (for instance, C<kern.cp_time>).

In other circumstances, a reference to a hash is returned, when the
variable represents a heterogeneous collection of values (for
instance, C<kern.clockrate>, C<vm.vmtotal>). In these cases, the
hash key names are reasonably self-explanatory, however, passing
familiarity with kernel data structures is expected.

A certain number of opaque variables are fully decoded (and the
results are returned as hashes), whereas the C<sysctl> binary renders
them as a raw hexdump (for example, C<net.inet.tcp.stats>).

=item sysctl_set

Perform a system call to set a sysctl variable to a new value.

  if( !sysctl_set( 'net.inet.udp.blackhole', 1 )) {
     warn "That didn't work: $!\n";
  }

Note: you must have C<root> privileges to perform this, otherwise
your request will be politely ignored.

=item sysctl_description

Returns the description of the variable, instead of the contents
of the variable. The information is only as good as the developers
provide, and everyone knows that developers hate writing documentation.

  my $mib = 'kern.ipc.somaxconn';
  print "$mib is ", sysctl_description($mib), $/;
  # prints the following:
  # kern.ipc.somaxconn is Maximum pending socket connection queue size

=item sysctl_exists

Check whether the variable name exists. Returns true or false
depending on whether the name is recognised by the system.

Checking whether a variable exists does not perform the conversion
to the numeric OID (and the attendant caching).

=back

=head1 METHODS

An object-oriented interface is also available. This allows you
to set up an object that stores the name of a C<sysctl> variable,
and then you can retrieve its value as often as needed.

  my $lastpid = BSD::Sysctl->new( 'kern.lastpid' );
  while (1) {
    print $lastpid->get(), $/;
    sleep 1;
  }

This is handy when you want to monitor a number of variables. Just
store the objects in an array and loop over them:

  my @var;
  for my $v (@ARGV) {
    push @var, BSD::Sysctl->new($v);
  }
  print join(' ', map {"$$_:" . $_->get} @var), $/;

Note: the internal implementation uses a blessed scalar. Thus, you
may recover the name of the variable by dereferencing the object
itself.

=over 8

=item new

Create a new BSD::Sysctl object. Takes the name of the C<sysctl>
variable to examine.

=item get

Returns the current value of the C<sysctl> variable.

  my $value = $variable->get();

=item set

Set the value of the C<sysctl> variable. Returns true on success,
C<undef> on failure.

  $variable->set(99);

=item iterator

Creates an iterator that may be used to walk through the sysctl
variable tree. If no parameter is given, the iterator defaults
to the first entry of the tree. Otherwise, if a paramter is
given, it is decoded as a sysctl variable. If the decoding
fails, undef is returned.

  my $k = BSD::Sysctl->iterator( 'kern' );
  while ($k->next) {
    print $k->name, '=', $k->value, "\n";
  }

=item next

Moves the iterator to the next sysctl variable and loads the
variable's name and its current value.

=item name

Returns the name of the sysctl variable that the iterator
is currently pointing at. If the iterator has not started to
look at the tree (that is, C<next> has not yet been called),
undef is returned.

=item value

Returns the value of the sysctl variable that the iterator
is currently pointing at. If the iterator has not started to
look at the tree, undef is returned. Subsequent calls to
value() will perform a fresh fetch on the current sysctl
variable that the iterator is pointing at.

Some return values are references to hashes or arrays.

=item reset

The iterator is reset back to before the first sysctl variable
it initially began with (in other words, C<next> must be
called afterwards, in order to fetch the first variable.

=back

=head1 NOTES

Yes, you could manipulate C<sysctl> variables directly from Perl
using the C<syscall> routine, however, you would have to have to
jump through various arduous hoops, such as performing the
string-E<gt>numeric OID mapping yourself, packing arrays of C<int>s
and generally getting the argument lists right. That would be a
considerable amount of hassle, and prone to error. This module makes
it easy.

No distinction between ordinary and opaque variables is made on
FreeBSD. If you ask for a variable, you get it (for instance,
C<kern.geom.confxml>). This is good.

When setting a variable to an integer value, the value is passed
to the C routine as is, which calls C<strtol> (or C<strtoul>) to
perform the conversion. The C routine checks to see whether the
conversion succeeds.

The alternative would have been to let Perl handle the conversion.
The problem with this is that Perl tries to do the right thing and
returns 0 in the event of an invalid conversion, and setting many
C<sysctl> variables to 0 could bring down a system (for instance,



( run in 0.828 second using v1.01-cache-2.11-cpan-22024b96cdf )