On Linux, sysctl exposes selected kernel parameters through /proc/sys. It can inspect the running state, and an authorized write can change that state without rebooting. A configuration file is a separate instruction to a loader. Confusing these two layers produces a familiar incident: the desired value is on disk, but the kernel is doing something else.

This article covers Linux with procps-ng and systemd. BSD and macOS also have commands named sysctl, but their interfaces and persistence mechanisms are different. A key count collected on macOS does not establish anything about Linux’s procfs tree.

Read the interface you actually have

For ordinary names, kernel.ostype corresponds to /proc/sys/kernel/ostype; procps accepts slash separators too. Names containing literal dots need the documented separator rules, rather than a blind string replacement. Available keys depend on kernel configuration, loaded modules and the execution environment. The table is not a fixed schema across machines or even across one machine’s lifetime.

Normal procps output uses key = value; -n prints only the value. A successful read establishes an observation in the caller’s environment, not a durable policy. Some values change while you inspect them. Read only the keys needed for the diagnosis: even reads are not universally passive. The manual excludes vm.stat_refresh from ordinary enumeration because reading it flushes per-CPU statistics.

Persistence belongs to a particular loader

A runtime assignment does not create a persistent configuration file. Conversely, saving a drop-in does not apply it immediately. Identify which component applies settings at boot and on reload before reasoning about precedence.

For procps --system, same-named files in higher-priority directories mask lower-priority copies. The selected drop-ins are applied in filename order, regardless of directory; /etc/sysctl.conf is then read last. Systemd’s sysctl.d loader also combines directory priority with filename ordering, but does not directly read /etc/sysctl.conf. Distribution-provided links can still make that file participate through a drop-in. Inspect the installation rather than assuming the pathname alone settles the question.

This has two distinct override rules. A local file can replace a vendor file with the same basename, or a differently named file can override individual assignments by sorting later. Neither rule stops another service from writing the parameter after the loader finishes. Successful boot-time application and the value observed hours later are different facts.

Error policies are not interchangeable

Systemd’s sysctl.d documentation treats missing variables and permission failures as debug-level, nonfatal cases. Other assignment failures make its service fail after processing the remaining settings. A leading minus on an assignment suppresses failure for that assignment. These are systemd loader rules, not a promise about every invocation of procps sysctl.

Procps -e specifically ignores unknown-key errors; it does not mean every malformed value or denied write succeeds. Its configuration format also supports a leading minus to ignore an assignment’s error. Do not infer a portable exit status by combining options and error policies from different implementations.

When it breaks

A module-specific key may not exist when the boot loader runs. Check module availability and loader logs before concluding that a later read disproves the configuration syntax. Another writer may also overwrite a successfully applied value. Record the loader, file precedence, application time and subsequent effective value separately.

Containers add another boundary: mounts, permissions and namespaces affect visibility and write scope. Determine scope from the particular parameter’s documentation; a prefix such as net.* is not sufficient proof that a proposed change is isolated. Do not grant privileges or remount procfs merely to make a troubleshooting command work.

Stacked cards distinguish same-basename masking from ordering the selected filenames. A separate text chain shows a loaded value being changed by a later writer. Loader differences, the limited read-only probe and error-policy warnings remain explicit. Static source explanation; no article exercise was run for this graphic.
Loader selection and ordering precede a runtime value, which a later writer can change; the source check only reads.

Check it quickly

This proposed read-only exercise requires Linux, Python 3, procps-ng 4.0.4 and readable procfs; its exact live invocation remains unrun. It compares one ordinary key through both interfaces, then checks a nonexistent key. It does not enumerate unknown handlers, load configuration, write settings or test boot persistence.

import os
import subprocess
from pathlib import Path

def require_result(result, status, stdout, stderr):
    if (type(result.returncode) is not int or type(result.stdout) is not bytes
            or type(result.stderr) is not bytes
            or (result.returncode, result.stdout, result.stderr) != (status, stdout, stderr)):
        raise RuntimeError(f"unexpected sysctl result: {result!r}")

def read_sysctl(*args):
    return subprocess.run(
        ["sysctl", *args], capture_output=True, check=False, timeout=5,
        env={**os.environ, "LC_ALL": "C"})

require_result(read_sysctl("--version"), 0,
               b"sysctl from procps-ng 4.0.4\n", b"")
require_result(read_sysctl("kernel.ostype"), 0, b"kernel.ostype = Linux\n", b"")
require_result(read_sysctl("-n", "kernel.ostype"), 0, b"Linux\n", b"")
if Path("/proc/sys/kernel/ostype").read_bytes() != b"Linux\n":
    raise RuntimeError("unexpected procfs kernel type")
require_result(read_sysctl("-n", "kernel.xbcatm_audit_missing_key"), 1, b"",
               b"sysctl: cannot stat /proc/sys/kernel/xbcatm_audit_missing_key: "
               b"No such file or directory\n")
print("matching kernel type: Linux")
print("exact missing-key diagnostic accepted")

Expect the matching-value and exact-diagnostic messages only after all checks succeed. The C-locale negative control requires status 1, empty stdout and the complete missing-path diagnostic, including its newline. Permission errors, missing tools, timeouts, partial output and unexpected success fail instead. Another procps version or diagnostic requires separate review, not a looser substring match. Pure response tests do not validate procfs or a live command. sysctl --system and sysctl -p apply settings; they are not configuration-preview commands and do not belong in this read-only check.

Sources