Tutorial nsysctl version 2

Posted on 2021-03-08 - Updated on 2025-04-18

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

An object is identified by an Object Identifier (OID), which is a sequence of numbers. You can replace a number with a string to obtain an object name; for example, [1.1] becomes “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
Only “nsysctl” to 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> to display name: value:

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

step 5
-e” to use = as a separator:

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

-s <sep>” to use <sep> as a separator:

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

Step 6
-N” to hide the value:

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

Step 7
-n” to hide the 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 examples include: 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, which are 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 hexadecimal 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” to 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 examples include: 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 to disable a flag: Disable sysctl ANYBODY flag.


Step 17
-H” for Handler, showing Defined if the object has a value, and Undefined otherwise. (Properly, the handler is the kernel function associated with the object, 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.2025


Step 18
-D” ie 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. See 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>” to 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 also show 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 also handle a nvlist. This feature allows the implementation of 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” to print 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” to 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”: to show objects with the SKIP flag with -a.


Step 27
-V”: by default, -a hides an object without a value. 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 values (not defined in opaque.c) in hexadecimal 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 human-printable opaque values because their Format is handled:

  • 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 hexadecimal 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” attempts 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” uses a buffer of bufsize bytes for a value.
  • -f filename” read object name/value from filename (example file.conf).
  • -i” ignore unknown objects.
  • -q avoids showing some warnings.
  • -T” shows only variables that are settable via loader.
  • -W” displays only writable variables that are not statistical.
  • -X” equivalent to -xa.

Step 32
nsysctl name=value” sets 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 toggles a numeric or boolean value. If the value is 0, it becomes 1; if it is not 0, it becomes 0. If the value is an array, only the first index is affected.

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 this behavior 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. However, it provides options to explicitly show both internal and SKIP nodes.

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 for v, [-N | -Vh [b | o | x]]). It is important for the following steps.

Furthermore nsysctl uses the sysctlinfo interface, so it can handle an object up to 23/24 levels or an object with an empty level name (example “security.jail.param.allow.mount.”). Finally, the efficiency of retrieving all properties for 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 find useful properties to handle objects, printed 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.