Tutorial nsysctl version 2

Posted on 2021-03-08 - Updated on 2022-01-02

The nsysctl utility can get or set the state of the FreeBSD kernel at runtime. The system exposes the available parameters as objects of a “Management Information Base” (MIB), nsysctl can explore the MIB, print the properties of an object, get or set its value and show the output in human and machine readable formats.

An object is identified by an Object Identifier (OID), a series of numbers, it is possible to replace a number with a string to obtain an object name, example [1.1] -> “kern.ostype”.


Step 1
To install the port sysutils/nsysctl:

# cd /usr/ports/sysutils/nsysctl/ && make install clean

To add the package:

# pkg install nsysctl

Step 2
nsysctl” show usage

user@bsd:~/% nsysctl
usage: nsysctl [--libxo options [-r tagroot]] [-DdeFGgHIilnOpqTtvW]
               [-N | -h [b | o | x]] [-B bufsize] [-f filename] [-s sep]
               name[=value[,value]] ...
       nsysctl [--libxo options [-r tagroot]] [-DdeFGgHIklnOpqSTtvW]
               [-N | -Vh [b | o | x]] [-B bufsize] [-s sep] -a

step 3
-v” for version

user@bsd:~/% nsysctl -v
nsysctl 2.1

This tutorial is for nsysctl >= 2.0 (old version: 2019-02-19-nsysctl-tutorial.html).


step 4
nsysctl” with a name

user@bsd:~/% nsysctl kern.ostype
kern.ostype: FreeBSD

The output is name: value


step 5
-e” use = separator

user@bsd:~/% nsysctl -e kern.ostype
kern.ostype=FreeBSD

-s <sep>” use <sep> separator

user@bsd:~/% nsysctl -s ' - ' kern.ostype
kern.ostype - FreeBSD

Step 6
-N” hide value

user@bsd:~/% nsysctl -N kern.ostype
kern.ostype

Step 7
-n” hide name

user@bsd:~/% nsysctl -n kern.ostype
FreeBSD

Step 8
-d” for description

user@bsd:~/% nsysctl -d kern.ostype
kern.ostype: Operating system type: FreeBSD
user@bsd:~/% nsysctl -d kern.osrevision
kern.osrevision: Operating system revision: 199506

Step 9
-t” for type, defined in sys/sysctl.h and documented in sysctl(9)CONTROL FLAGS” Section, some example: node, integer, opaque, string, and so on

user@bsd:~/% nsysctl -dt kern.ostype
kern.ostype: Operating system type: string: FreeBSD
user@bsd:~/% nsysctl -dt kern.osrevision
kern.osrevision: Operating system revision: integer: 199506

Step 10
-F” for the format, for example an integer could represent a simple integer, a deciKelvin, a milliKelvin, and so on; the format is important also for opaque values described later

user@bsd:~/% nsysctl -dtF kern.osrevision
kern.osrevision: Operating system revision: integer: I: 199506
user@bsd:~/% nsysctl -dtF dev.cpu.0.temperature
dev.cpu.0.temperature: integer: IK: 27.950006C

They are documented in sysctl(9) -> “DESCRIPTION OF ARGUMENTS” Section -> format.


Step 11
-x for (numeric) value in hex format

user@bsd:~/% nsysctl -dtFx kern.ostype
kern.ostype: Operating system type: string: A: FreeBSD
user@bsd:~/% nsysctl -dtFx kern.osrevision
kern.osrevision: Operating system revision: integer: I: 0x00030b52

Step 12
-b” for value in binary format without newline

user@bsd:~/% nsysctl -dtFb kern.ostype
kern.ostype: Operating system type: string: A: FreeBSDuser@bsd:~/%
user@bsd:~/%
user@bsd:~/% nsysctl -dtFb kern.osrevision
kern.osrevision: Operating system revision: integer: I: R
                                                         ?user@bsd:~/%
user@bsd:~/%

Step 13
-p” show “[PROPERTY-NAME]:”

user@bsd:~/% nsysctl -pdtF -s ', ' kern.ostype
[NAME]: kern.ostype, [DESCRIPTION]: Operating system type, [TYPE]: string,
[FORMAT]: A, [VALUE]: FreeBSD

Step 14
-l” for aggregation label, useful for the prometheus_sysctl_exporter utility

user@bsd:~/% nsysctl -pldtF -s ', ' kern.features.scbus
[NAME]: kern.features.scbus, [LABEL]: feature, [DESCRIPTION]: SCSI devices
support, [TYPE]: integer, [FORMAT]: I, [VALUE]: 1

Step 15
-O” for OID (the sysctl system call finds an object matching its OID)

user@bsd:~/% nsysctl -pOldtF -s ', ' kern.ostype
[OID]: 1.1, [NAME]: kern.ostype, [LABEL]: , [DESCRIPTION]: Operating system
type, [TYPE]: string, [FORMAT]: A, [VALUE]: FreeBSD

Step 16
-g” for flags (number) and “-G” for true flags list, they are defined in sys/sysctl.h and documented in sysctl(9)CONTROL FLAGS” Section, some example: RD, WR, ANYBODY, TUN, SKIP, and so on

user@bsd:~/% nsysctl -pyldtFgG -s ', ' kern.ostype
[OID]: 1.1, [NAME]: kern.ostype, [LABEL]: , [DESCRIPTION]: Operating system
type, [TYPE]: string, [FORMAT]: A, [FLAGS-RAW]: 2147778560, [FLAGS]: RD MPSAFE
CAPRD, [VALUE]: FreeBSD

Example: Disable sysctl ANYBODY flag.


Step 17
-H” for Handler, Defined if the object has a value, Undefined otherwise (properly the handler is the object kernel function, mainly, used to read or write a value)

user@bsd:~/% nsysctl -pyldtFgGH -s ', ' kern.ostype
[OID]: 1.1, [NAME]: kern.ostype, [LABEL]: , [DESCRIPTION]: Operating system
type, [TYPE]: string, [FORMAT]: A, [FLAGS-RAW]: 2147778560, [FLAGS]: RD MPSAFE
CAPRD, [HANDLER]: Defined, [VALUE]: FreeBSD

Furthermore, the OID of a node object with a Defined handler can be extended, example [1.14.1.<pid>] (“kern.proc.pid”) in the sysctl(3) manual

user@bsd:~/% nsysctl -tH kern.proc.pid
nkern.proc.pid: node: Defined

sysctlbyname-improved can handle an extended name like “kern.proc.pid.2021


Step 18
-D” Equivalent to: “-d” “-F” “-G” “-H” “-l” “-O” “-t

user@bsd:~/% nsysctl -pD -s ', ' kern.ostype
[OID]: 1.1, [NAME]: kern.ostype, [LABEL]: , [DESCRIPTION]: Operating system
type, [TYPE]: string, [FORMAT]: A, [FLAGS]: RD MPSAFE CAPRD, [HANDLER]: Defined,
[VALUE]: FreeBSD

Step 19
--libxo” for emitting: text, XML, JSON, or HTML output, xo_parse_args(3),

text

user@bsd:~/% nsysctl --libxo=text -pD kern.ostype
[OID]: 1.1: [NAME]: kern.ostype: [LABEL]: : [DESCRIPTION]: Operating system
type: [TYPE]: string: [FORMAT]: A: [FLAGS]: RD MPSAFE CAPRD: [HANDLER]: Defined:
[VALUE]: FreeBSD

XML

user@bsd:~/% nsysctl --libxo=xml,pretty -D kern.ostype
<object>
  <OID>1.1</OID>
  <name>kern.ostype</name>
  <label></label>
  <description>Operating system type</description>
  <type>string</type>
  <format>A</format>
  <flags>
    <flag>RD</flag>
    <flag>MPSAFE</flag>
    <flag>CAPRD</flag>
  </flags>
  <handler>Defined</handler>
  <value>FreeBSD</value>
</object>

JSON

user@bsd:~/% nsysctl --libxo=json,pretty -dtF kern.ostype
{
  "object": [
    {
      "name": "kern.ostype",
      "description": "Operating system type",
      "type": "string",
      "format": "A",
      "value": "FreeBSD"
    }
  ]
}

HTML (the sysctl-mib-html project provides an ad-hoc solution for html)

user@bsd:~/% nsysctl --libxo=html,pretty -dtF kern.ostype
<div class="line">
  <div class="data" data-tag="name">kern.ostype</div>
  <div class="label">: </div>
  <div class="data" data-tag="description">Operating system type</div>
  <div class="label">: </div>
  <div class="data" data-tag="type">string</div>
  <div class="label">: </div>
  <div class="data" data-tag="format">A</div>
  <div class="label">: </div>
  <div class="data" data-tag="value">FreeBSD</div>
  <div class="label">
</div>

Step 20
-r <tag-root>” specify a tag-root with libxo

user@bsd:~/% nsysctl --libxo=xml,pretty -r "MIB"  kern.ostype
<MIB>
  <object>
    <name>kern.ostype</name>
    <value>FreeBSD</value>
  </object>
</MIB>

Step 21
nsysctl name” shows only the descendant leaves of name by default

user@bsd:~/% nsysctl -N compat
compat.ia32.maxvmem
compat.ia32.maxssiz
compat.ia32.maxdsiz
user@bsd:~/%
user@bsd:~/% nsysctl --libxo=xml,pretty -N compat
<object>
  <name>compat.ia32.maxvmem</name>
</object>
<object>
  <name>compat.ia32.maxssiz</name>
</object>
<object>
  <name>compat.ia32.maxdsiz</name>
</object>

-I” to show also internal nodes, libxo adds <children> tag

user@bsd:~/% nsysctl -NI compat
compat
compat.ia32
compat.ia32.maxvmem
compat.ia32.maxssiz
compat.ia32.maxdsiz
user@bsd:~/% nsysctl --libxo=xml,pretty -NI compat
<object>
  <name>compat</name>
  <children>
    <object>
      <name>compat.ia32</name>
      <children>
        <object>
          <name>compat.ia32.maxvmem</name>
        </object>
        <object>
          <name>compat.ia32.maxssiz</name>
        </object>
        <object>
          <name>compat.ia32.maxdsiz</name>
        </object>
      </children>
    </object>
  </children>
</object>

Step 22
The string value of some object is parsed to show structured output via libxo

user@bsd:~/% nsysctl --libxo=xml,pretty vm.phys_free

List of parsed objects:

  • debug.witness.fullgraph
  • kern.conftxt
  • vm.phys_free

Step 23
nsysctl can handle also a nvlist, libnv(9). This feature allows to implement a non-primitive object value without hardcoding its C structure, see opaque later; example to build a nvlist object: sysctl-libnv.

% nsysctl -dF nv.campania
nv.campania: Administrative region of Italy: NV:
Capital=Napoli
Population=5869029
Cities=Avellino Benevento Caserta Napoli Salerno
% nsysctl --libxo=xml,pretty -dtF nv.campania
<object>
  <name>nv.campania</name>
  <description>Administrative region of Italy</description>
  <type>opaque</type>
  <format>NV</format>
  <value>
    <nvlist>
      <nv>
        <name>Capital</name>
        <value>Napoli</value>
        <nvtype>NV_TYPE_STRING</nvtype>
      </nv>
      <nv>
        <name>Population</name>
        <value>5869029</value>
        <nvtype>NV_TYPE_NUMBER</nvtype>
      </nv>
      <nv>
        <name>Cities</name>
        <value>Avellino</value>
        <value>Benevento</value>
        <value>Caserta</value>
        <value>Napoli</value>
        <value>Salerno</value>
        <nvtype>NV_TYPE_STRING_ARRAY</nvtype>
      </nv>
    </nvlist>
  </value>
</object>

Step 24
-a” All objects

user@bsd:~/% nsysctl -a
kern.ostype: FreeBSD
kern.osrelease: 13.0-CURRENT
kern.osrevision: 199506
...

FreeBSD provides thousands of objects.


Step 25
-S” show “sysctl.*” subtree with -a, these objects are useful to write a software to explore the MIB

user@bsd:~/% nsysctl -SOdNa | less
0.1: sysctl.name:
0.2: sysctl.next:
0.3: sysctl.name2oid:
0.4: sysctl.oidfmt:
0.5: sysctl.oiddescr:
0.6: sysctl.oidlabel:
0.7: sysctl.nextnoskip:
0.10: sysctl.objidextended_byname: Object ID by its name eventually extended
0.11: sysctl.objname: Object name by its OID
0.12: sysctl.objid_byname: Object ID by its name
0.13: sysctl.objfakename: Object (possible fake) name
0.14: sysctl.objfakeid_byname: Object (possible fake) ID by its name
0.15: sysctl.objdesc: Object description string
0.16: sysctl.objdesc_byname: Object description by its name
0.17: sysctl.objlabel: Object label
0.18: sysctl.objlabel_byname: Object label by its name
0.19: sysctl.objkind: Object kind (flags and type)
0.20: sysctl.objkind_byname: Object kind by its name
0.21: sysctl.objfmt: Object format string
0.22: sysctl.objfmt_byname: object format string by its name
0.23: sysctl.nextobjnode: Next object (internal node or leaf)
0.24: sysctl.nextobjnode_byname: Next object name (internal node or leaf)
0.25: sysctl.nextobjleaf: Next object (only leaf)
0.26: sysctl.nextobjleaf_byname: Next object name (only leaf)
0.27: sysctl.serobj: Serialize object properties
0.28: sysctl.serobj_byname: Serialize object by its name
0.29: sysctl.serobjnextnode: Serialize object with next-node-OID
0.30: sysctl.serobjnextnode_byname: Serialize object by its name with next-node-
name
0.31: sysctl.serobjnextleaf: Serialize object with next-leaf-OID
0.32: sysctl.serobjnextleaf_byname: Serialize object by its name with next-leaf-
name
0.33: sysctl.objhashandler: Object has a handler
0.34: sysctl.objhashandler_byname: Object has a handler by its name
0.35: sysctl.fakenextobjleafnoskip: Next object (only leaf) avoiding SKIP flag

Step 26
-k”: show objects with the SKIP flag with -a.


Step 27
-V”: -a hides an object without a value by default, this option disable this feature.

user@bsd:~/% nsysctl -aV

Tip: -a hides nodes without value so -I is useless without -V

user@bsd:~/% nsysctl -aIV

Step 28
-o” to show opaque value (not defined in opaque.c) in hex format up to 16 bytes

user@bsd:~/% nsysctl -ato | grep opaque
kern.clockrate: opaque: { hz = 1000, tick = 1000, profhz = 8128, stathz = 127 }
kern.proc.all: opaque: Format:S,proc Length:490688 Dump:0x4004000000000000000000
0000000000...
kern.file: opaque: Format:S,xfile Length:197632 Dump:0x80000000000000007b0a0000e
9030000...
kern.boottime: opaque: { sec = 1614296786, usec = 464261 } Fri Feb 26 00:46:26
2021
kern.ipc.shmsegs: opaque: Format: Length:19968 Dump:0xe9030000e9030000e9030000e9
030000...
...

without “-o” values not defined in opaque.c are hidden by -a

user@bsd:~/% nsysctl -at | grep opaque
kern.clockrate: opaque: { hz = 1000, tick = 1000, profhz = 8128, stathz = 127 }
kern.boottime: opaque: { sec = 1614296786, usec = 464261 } Fri Feb 26 00:46:26
2021
...

List of defined opaque, properly Formats for type opaque:

  • S,clockinfo
  • S,bios_smap_xattr
  • S,efi_map_header
  • S,input_id
  • S,loadavg
  • S,pagesizes
  • S,timeval
  • S,vmtotal
  • NV (libnv)

Step 29
-x is equivalent to -o but print all the bytes, moreover OID and flags are shown in hex format

user@bsd:~/% nsysctl -ONg compat.ia32.maxvmem
2147482900.2147481617.2147481614: compat.ia32.maxvmem: 3222016000
user@bsd:~/% nsysctl -ONgx compat.ia32.maxvmem
7ffffd14.7ffff811.7ffff80e: compat.ia32.maxvmem: c00c1000

Step 30
-h” try to show values in a human-friendly format, it depends on the ‘h’ field modifier of libxo, please refer to the-humanize-modifier-h for a more thorough description.


Step 31

  • -A” equivalent to -oa.
  • -B bufsize” use a buffer of bufsize bytes for a value.
  • -f filename” read object name/value from filename (example file.conf).
  • -i” ignore unknown objects.
  • -q avoid to show some warning.
  • -T” show only variables that are settable via loader.
  • -W” display only writable variables that are not statistical.
  • -X” equivalent to -xa.

Step 32
nsysctl name=value” set a new value

user@bsd:~/% su
Password:
root@bsd:/home/user/# nsysctl kern.maxprocperuid=1000
kern.maxprocperuid: 8211 -> 1000
root@bsd:/home/user/# nsysctl --libxo=xml,pretty kern.maxprocperuid=8211
<object>
  <name>kern.maxprocperuid</name>
  <value>1000</value>
  <newvalue>8211</newvalue>
</object>
root@bsd:/home/user/# exit
exit
user@bsd:~/%

To set a numeric array: “nsysctl name=value,value,value,value”.


Step 33
-z Toggle numeric or boolean value, if the value is 0 becomes 1, if it is not 0 becomes 0, if the value is an array only the first index takes effect

user@bsd:~/% nsysctl -z hw.snd.default_unit
hw.snd.default_unit: 0 -> 1

Step 34
nsysctl can get a list of objects

root@bsd:/home/user/# nsysctl kern.ostype vm.loadavg kern.maxprocperuid=9000
kern.ostype: FreeBSD
vm.loadavg: { 0.15 0.13 0.18 }
kern.maxprocperuid: 8211 -> 9000
root@fbsd:/home/user/#

Step 35
Comparison sysctl - nsysctl

sysctl(8), prints internal and SKIP nodes with -aN, -ad and -at, only leaves avoiding SKIP nodes otherwise, to reproduce with nsysctl:

sysctl nsysctl
% sysctl -aN % nsysctl -aNIk
% sysctl -ad % nsysctl -adIk
% sysctl -at % nsysctl -atIk

Internal nodes have not a value (Undefined Handler), so nsysctl hides them by default, it gives the possibility to choose explicitly to show them and SKIP nodes via options.

Extra nsysctl options: --libxo, -D, -F, -G, -g, -H, -I, -k, -l, -O, -r, -p, -S, -s, -V, -v and -z.

The options are not mutually exclusive (except v, [-N | -Vh [b | o | x]]), this feature is important for the next steps.

Furthermore nsysctl uses the sysctlinfo interface, so it can handle an object with 23/24 levels or an object with an empty level name (example “security.jail.param.allow.mount.”), finally the efficiency to get all the properties about an object is improved.

user@bsd:~/% nsysctl x1
x1.x2.x3.x4.x5.x6.x7.x8.x9.x10.x11.x12.x13.x14.x15.x16.x17.x18.x19.x20.x21.x22.
x23.x24: 24
user@bsd:~/% nsysctl security.jail.param.allow.mount.
security.jail.param.allow.mount.: 0

Step 36
To know useful properties to handle objects in “tabular” form

user@bsd:~/% nsysctl -pdtFGH -s " - " hw.snd

Screenshot to configure Elantech Touchpad

user@bsd:~/% nsysctl -adtFG -s ", " | grep elantech


Step 37/
To debug, printing everything, avoiding to recompile the kernel with SYSCTL_DEBUG

user@bsd:~/% nsysctl -pDIkVgSa -s " - "
user@bsd:~/% nsysctl --libxo=xml,pretty -r "MIB" -DIkVgSa

Step 38
Frequently Asked Questions:

Manual Page?
nsysctl(8).
Source code?
https://gitlab.com/alfix/nsysctl.
How can I customize nsysctl?
nsysctl.c for getting/setting basic types, opaque.c for opaque values and special_values.c for parsed strings.
Can I write my sysctl-like utility?
Yes, you can, https://gitlab.com/alfix/sysctlmibinfo2 is an easy API to explore the sysctl MIB.
Graphical User Interface?
https://gitlab.com/alfix/sysctlview.