DEVD.CONF(5)
π DEVD.CONF(5) π
bestie, this is the DEVD.CONF(5) page from the File Formats Manual β the whole vibe is the configuration file format for devd(8). no cap, itβs giving very specific config-file energy. π
β¨ NAME β¨
devd.conf β configuration file format for devd(8)
πΈ DESCRIPTION πΈ
π General Syntax π
A devd(8) configuration has two general features: statements and comments. Every statement ends with a semicolon. Many statements can contain substatements, and those are also terminated with a semicolon. π
The following statements are supported:
attachβ specifies various matching criteria and actions to perform when a newly attached device matches said criteria.detachβ specifies various matching criteria and actions to perform when a newly detached device matches said criteria.nomatchβ specifies various matching criteria and actions to perform when no device driver currently loaded in the kernel claims a (new) device.notifyβ specifies various matching criteria and actions to perform when the kernel sends an event notification to userland.optionsβ specifies various options and parameters for the operation ofdevd(8).
Statements may occur in any order in the configuration file, and may be repeated as often as required. Further details on the syntax and meaning of each statement and their substatements are explained below. π
Each statement, except options, has a priority (an arbitrary number) associated with it, where 0 is defined as the lowest priority. If two statements match the same event, only the action of the statement with highest priority will be executed. In this way generic statements can be overridden for devices or notifications that require special attention. π
The general syntax of a statement is:
statement priority {
substatement "value";
...
substatement "value";
};
π Sub-statements π
The following sub-statements are supported within the options statement.
directory "/some/path";β adds the given directory to the list of directories from whichdevd(8)will read all files named"*.conf"as further configuration files. Any number ofdirectorystatements can be used.pid-file "/var/run/devd.pid";β specifies PID file.set regexp-name "(some|regexp)";β creates a regular expression and assigns it to the variableregexp-name. The variable is available throughout the rest of the configuration file. If the string begins with!, it matches if the regular expression formed by the rest of the string does not match. All regular expressions have an implicit^$around them.
The following sub-statements are supported within the attach and detach statements.
action "command";β command to execute upon a successful match. Example"/etc/pccard_ether $device-name start".class "string";β this is shorthand formatch "class" "string".device-name "string";β this is shorthand formatch "device-name" "string". This matches a device named string, which is allowed to be a regular expression or a variable previously created containing a regular expression. Thedevice-namevariable is available for later use with theactionstatement.match "variable" "value";β matches the content of value against variable; the content of value may be a regular expression. Not required duringattachnordetachevents since thedevice-namestatement takes care of all device matching. For a partial list of variables, see below.media-type "string";β for network devices,media-typewill match devices that have the given media type. Valid media types are:"Ethernet","802.11", and"ATM".subdevice "string";β this is shorthand formatch "subdevice" "string".
The following sub-statements are supported within the nomatch statement.
action "command";β same as above.match "variable" "value";β matches the content of value against variable; the content of value may be a regular expression. For a partial list of variables, see below.
The following sub-statements are supported within the notify statement. The notify variable is available inside this statement and contains, a value, depending on which system and subsystem that delivered the event. π¦
action "command";β command to execute upon a successful match. Example"/etc/rc.d/power_profile $notify".match "system | subsystem | type | notify" "value";β any number ofmatchstatements can exist within anotifystatement; value can be either a fixed string or a regular expression. Below is a list of available systems, subsystems, and types.media-type "string";β see above.
π Variables that can be used with the match statement π
A partial list of variables and their possible values that can be used together with the match statement. The variables are published by the bus based on characteristics of the device that generated the event (for device events). Variables for other classes of events are dependent on those events. π
*β the entire message from the current event._β the entire message from the current event, after the initial type character.timestampβ the time this event was processed, in seconds since 1970 dot fraction.busβ device name of parent bus.cdevβ device node path if one is created by thedevfs(4)filesystem.classβ device class.commβ executable name (kernel).coreβ path to core file (kernel).deviceβ device ID.devclassβ device Class (USB).devsubclassβ device Sub-class (USB).device-nameβ name of attached/detached device.endpointsβ endpoint count (USB).functionβ card functions.interfaceβ interface ID (USB).intclassβ interface Class (USB).intprotocolβ interface Protocol (USB).intsubclassβ interface Sub-class (USB).jailβ jail name for the process triggering the rule (RCTL).modeβ peripheral mode (USB).notifyβ match the value of thenotifyvariable.parentβ parent device.pidβ PID of the process triggering the rule (RCTL).portβ hub port number (USB).productβ product ID (USB).releaseβ hardware revision (USB).ruidβ real UID of the process triggering the rule (RCTL).ruleβ rule (RCTL).sernumβ serial Number (USB).slotβ card slot.subvendorβ sub-vendor ID (PCI).subdeviceβ sub-device ID (PCI).subsystemβ matches a subsystem of a system, see below.systemβ matches a system type, see below.typeβ type of notification, see below.vendorβ vendor ID.
π₯ Notify matching π₯
A partial list of systems, subsystems, and types used within the notify mechanism.
Hereβs the System / Subsystem / Type situation, with descriptions attached. π
ACPIβ events related to the ACPI Subsystem.ACPI,ACADβ AC line state ($notify=0x00is offline,0x01is online).ACPI,Buttonβ button state ($notify=0x00is power,0x01is sleep).ACPI,CMBATβ battery events.ACPI,Dockβ dock state ($notify=0x00is undocked,0x01is docked).ACPI,Lidβ lid state ($notify=0x00is closed,0x01is open).ACPI,PROCESSORβ processor state/configuration ($notify=0x81is a change in available Cx states).ACPI,Resumeβ resume notification.ACPI,Suspendβ suspend notification.ACPI,Thermalβ thermal zone events.
AEON,power,pressβ the power button on an Amiga has been pressed.CAMβ events related to thecam(4)system.CAM,periphβ events related to peripheral devices.CAM,periph,errorβ generic errors.CAM,periph,timeoutβ command timeouts.
CARPβ events related to thecarp(4)protocol.CARP,vhid@inetβ the"subsystem"contains the actual CARP vhid and the name of the network interface on which the event took place.CARP,vhid@inet,MASTERβ node become the master for a virtual host.CARP,vhid@inet,BACKUPβ node become the backup for a virtual host.
coretempβ events related to thecoretemp(4)device.coretemp,Thermalβ notification that the CPU core has reached critical temperature.coretemp,Thermal,temperatureβ string containing the temperature of the core that has become too hot.
DEVFSβ system listed on its own in the table.ETHERNET,inet,IFATTACHβ notification when the default VNET instance of theinetinterface is attached.
πΎ GEOM β the disk-ish corner of the universe
Okay so GEOM is all the events coming out of the geom(4) framework. The difference compared to DEVFS is that GEOM only includes disk-like devices. That's it, that's the whole vibe check. π
GEOMβ Events related to thegeom(4)framework. The difference compared toDEVFSis that GEOM only includes disk-like devices.GEOM/DEV/CREATEβ Ageom(4)provider is created. New disk just dropped β¨GEOM/DEV/DESTROYβ Ageom(4)provider is destroyed. gone, reduced to atoms πGEOM/DEV/GEOM::physpathβ The physical path of a device has changed.GEOM/DEV/GEOM::rotation_rateβ The rotation rate of the disk has changed.GEOM/DEV/MEDIACHANGEβ Physical media has changed.GEOM/DEV/SIZECHANGEβ Ageom(4)provider size has changed.
π IFNET β network interface drama
IFNETβ the base system. Lowkey the star of the show here is the subsystem field:
Heads up bestie: for every IFNET event, the βsubsystemβ is the actual name of the network interface on which the event took place. Not a category, not a label β the interface name itself. iconique π
IFNET/ inet β the βsubsystemβ is the actual name of the network interface on which the event took place.IFNET/ inet /LINK_UPβ Carrier status changed to UP. we're so back π₯IFNET/ inet /LINK_DOWNβ Carrier status changed to DOWN. it's giving disconnected πIFNET/ inet /ATTACHβ The network interface is attached to the system.IFNET/ inet /DETACHβ The network interface is detached from the system.IFNET/ inet /RENAMEβ The network interface is renamed.IFNET/ inet /ADDR_ADDβ The network interface address added.IFNET/ inet /ADDR_DELβ The network interface address removed.
π§ kernel β the big boss events
kernel/signal/coredumpβ Notification that a process has crashed and dumped core. rip bozo, we have a core file now πkernel/power/resumeβ Notification that the system has woken from the suspended state. good morning sunshine βοΈ
π½ nvme β controller tea
Controller events provide the controller name (for example, nvme0) in $name. Slay, now you know who's talking to you.
nvme/controllerβ Controller events provide the controller name (for example,nvme0) in$name.nvme/controller/SMART_ERRORβ A SMART Critical Warning State change has happened.$statehas a hex bitmask of the bits that changed, as defined in the NVMe Standard for Critical Warning field of log page 2 βSMART / Health Information Logβ:0x1β Spare capacity below threshold0x2β Temperature outside acceptable range0x4β Reliability of media degraded0x8β Media placed into read-only mode0x10β Volatime memory backup failure0x20β Persistent memory read-only or degraded
nvme/controller/RESETβ A controller reset event has happened.$eventis one ofβstartβ,βsuccessβ, andβtimed_outβrepresenting the start of a controller reset, the successful completion of a controller reset, or a timeout while waiting for the controller to reset, respectively.nvme/controller/RECONNECTβ An NVMe over Fabrics host has disconnected and is requesting a reconnect. bestie please come back π₯Ί
π PMU β the power management unit chronicles
PMU is your notification hookup for events from various types of Power Management Units. There's a lot here, so buckle up π’
β‘ PMU / AC β wall power behaviour
PMU/ACβ Notifications of AC power related events.PMU/AC/overvoltageβ An over-voltage condition was detected on the AC power line. too much voltage, that's not slay π¬PMU/AC/pluggedβ Power has been applied to the AC power line.PMU/AC/unpluggedβ Power has been removed from the AC power line. on battery now, stay calm π«Ά
π PMU / Battery β the whole battery saga
PMU/Batteryβ the battery subsystem itself.PMU/Battery/absentβ Battery is no longer absent. not me misreading that β yes, βno longer absentβ, that's the wording, copy it exactly β¨PMU/Battery/chargedβ The battery has become charged. full bars energy πPMU/Battery/chargingβ The battery has started charging.PMU/Battery/disconnectedβ The battery has been disconnected.PMU/Battery/high-tempβ The battery reported a temperature over the limit. she's running hot π₯PMU/Battery/low-tempβ The battery reported a temperature under the limit.PMU/Battery/pluggedβ The battery has become plugged (eg connected).PMU/Battery/shutdown-thresholdβ The power in the battery has fallen below the shutdown threshold. you have approximately zero seconds left, save your work πPMU/Battery/warning-thresholdβ The power in the battery has fallen below the warn the user threshold.
ποΈ PMU / Button β button go press
β¨οΈ PMU / keys β keyboard keys doing things
PMU/keysβ One of the keys on theadb(4)keyboard has been pressed.PMU/keys/brightnessβ A brightness level change has been requested. Direction is in the$notifyvariable.PMU/keys/muteβ The mute key π€PMU/keys/volumeβ A volume level change has been requested. Direction is in the$notifyvariable.PMU/keys/ejectβ An ejection has been requested.
πͺ PMU / lid β laptop lid lore
PMU/lid/closeβ Thepmc(4)device has detected the lid closing.PMU/lid/openβ Thepmc(4)device has detected the lid openinging. (That's the manpage's spelling, not mine, I promise β keeping it forever π )
π PMU / POWER β the AC line state report
PMU/POWER/ACLINEβ Thepmc(4)device has detected an AC line state ($notify=0x00is offline,0x01is online).
π PMU / USB β power pins going feral
PMU/USB/overvoltageβ An over-voltage condition on the power lines for the USB power pins.PMU/USB/pluggedβ A device has been plugged into a USB device.PMU/USB/undervoltageβ An under-voltage condition on the power lines for the USB power pins.PMU/USB/unpluggedβ A device has been unplugged from a USB device.
π RCTL β resource control events
RCTLβ Events related to therctl(8)framework.RCTL/rule/matchedβ A rule with action specified as"devctl"was triggered. the rule did its little job, periodt β¨
π USB β plug it in, pull it out
USBβ Events related to the USB subsystem.USB/DEVICE/ATTACHβ USB device is attached to the system.USB/DEVICE/DETACHβ USB device is detached to the system.USB/INTERFACE/ATTACHβ USB interface is attached to a device.USB/INTERFACE/DETACHβ USB interface is detached from a device.
ποΈ VFS β filesystem mounting behaviour
VFSβ Events from the vfs system.VFS/FSβ Events that change what is mounted to the system.VFS/FS/MOUNTβ Notification of a filesystem is mounted for the first time.VFS/FS/REMOUNTβ Notification of a filesystem is remounted (whether or not the options actually change).VFS/FS/UNMOUNTβ Notification of a filesystem being unmounted. bye bestie, hope to see you at the next mount π¦- System
VT, SubsystemBELL, TypeRINGβ bestie, the console bell literally rang. That's it, that's the notification. Peepvt(4)for the whole story.
- System
ZFS, SubsystemZFSβ all the tea about the ZFS subsystem lives here. Seezfsd(8)and/etc/devd/zfs.conffor the receipts.
- System
SNDβ events spilling out of thesound(4)driver, no cap. - System
SND, SubsystemCONN, TypeINβ an input device got connected, and it's named in thecdevvariable. π - System
SND, SubsystemCONN, TypeOUTβ same energy but output, also named incdev. - System
SND, SubsystemCONN, TypeNODEVβ zero devices connected. Nobody's home. π
So like, a link state change to UP on the interface "fxp0" would give you this notify event, iconic:
system=IFNET subsystem=fxp0 type=LINK_UP
And an AC line state change to "offline"? That one drops this event:
system=ACPI subsystem=ACAD notify=0x00
π Comments π
Okay so comments can show up literally anywhere whitespace can show up in a config file. And because the devs wanted to appeal to programmers of all kinds, you can write them C-style, C++-style, or shell/Perl-style. Versatile queen behavior. π
C-style comments start with the two characters /* (slash, star) and end with */ (star, slash). Because they're completely delimited by those characters, you can use them to comment only a portion of a line, or to span multiple lines. Slay.
β οΈ C-style comments cannot be nested. Like, at all. This next one is not valid, because the whole comment ends at the first */:
/* This is the start of a comment.
This is still part of the comment.
/* This is an incorrect attempt at nesting a comment. */
This is no longer in any comment. */
C++-style comments start with the two characters // (slash, slash) and keep going to the end of the physical line. They cannot be continued across multiple physical lines β so if you want one logical comment to span multiple lines, every single line has to carry its own // pair. Example time:
// This is the start of a comment. The next line
// is a new comment, even though it is logically
// part of the previous comment.
π¦ Notes on Variable Expansion π¦
Variables get expanded when you put a $ sign in front of them. Any text right after that sign β starting with a letter, a minus sign -, an underscore _, or an asterisk * β counts as an internal variable and gets expanded accordingly. And if that variable doesn't exist? It just silently expands to an empty string. No drama, no error, just nothing. π
So consequently, if your intention is to pass a sh(1) variable, it has to be surrounded by braces so it doesn't get mistaken for an internal variable. Periodt.
See "EXAMPLES" for a detailed example, iykyk.
To prevent issues with special shell characters, the following happens for each variable $foo:
- The characters
$'are inserted. - The string
$foois removed. - The value of the
foovariable is inserted into the buffer with all single quote characters prefixed by a backslash. - A final
'is inserted.
See sh(1) for what this construct means. It's safe in all contexts β except one: inside single quotes. π«£ So if foo=meta and bar=var, then a rule like this:
action "echo '$foo $bar'";
will be presented to the shell via system(3) as:
echo '$'meta' $'var''
which produces this as its output:
$meta $var
...which is an unanticipated result, bestie. A future version of this software will change this behavior. Users are discouraged from using single quotes inside an action value without due care. You've been warned. π
The above should be written as:
action "echo $foo' '$bar"
to produce a single argument to echo. Given the above expansion, juxtaposing bare variables with single quote expressions will produce the right output, regardless of the value of the variable. Chef's kiss. π§
β¨ FILES β¨
/etc/devd.confβ thedevd(8)configuration file./etc/devdβ a directory thatdevdsearches for additional configuration files./usr/local/etc/devdβ a directory thatdevdalso searches for additional configuration files.
π EXAMPLES π
#
# This will catch link down events on the interfaces fxp0 and ath0
#
notify 0 {
match "system" "IFNET";
match "subsystem" "(fxp0|ath0)";
match "type" "LINK_DOWN";
action "logger $subsystem is DOWN";
};
#
# Match lid open/close events
# These can be combined to a single event, by passing the
# value of $notify to the external script.
#
notify 0 {
match "system" "ACPI";
match "subsystem" "Lid";
match "notify" "0x00";
action "logger Lid closed, we can sleep now!";
};
notify 0 {
match "system" "ACPI";
match "subsystem" "Lid";
match "notify" "0x01";
action "logger Lid opened, the sleeper must awaken!";
};
#
# Match a USB device type
#
notify 0 {
match "system" "USB";
match "subsystem" "INTERFACE";
match "type" "ATTACH";
match "intclass" "0x0e";
action "logger USB video device attached";
};
#
# Try to configure ath and iwn devices with pccard_ether
# as they are attached.
#
attach 0 {
device-name "(ath|iwn)[0-9]+";
action "/etc/pccard_ether $device-name start";
};
#
# Stop ath and iwn devices as they are detached from
# the system.
#
detach 0 {
device-name "(ath|iwn)[0-9]+";
action "/etc/pccard_ether $device-name stop";
};
The following example illustrates the difference between internal and shell variables β this is the one, watch closely:
attach 20 {
device-name "umodem[0-9]+";
match "vendor" "0x2047";
match "product" "0x001(0|3|4)";
match "interface" "0";
action "cd /dev; p=$product; dn=$device-name; \
un=$(sysctl -n dev.umodem.${dn#umodem}.ttyname); \
chmod 666 cua${un}; ln -sf cua${un} mspfet${p#0x}";
};
So product and device-name are internal variables. Their contents get initially assigned to the shell variables p and dn, respectively. Then variable dn is used inside a shell command substitution, assigning to shell variable un. Finally, that shell variable is used in two other shell statements, where it needs to be wrapped in braces in order to prevent it from being considered an internal variable to devd. The way it all clicks together?? Obsessed. π
The installed /etc/devd.conf has many additional examples, so go snoop.
π SEE ALSO π
cam(4), coretemp(4), devfs(4), re_format(7), devd(8)
π BUGS π
The variable expansion's interaction with single quotes is suboptimal and surprising. Like, genuinely rude of it. π
That's the whole vibe, bestie β go forth and write the prettiest devd config of your life. This slice of manpage lore is from the Debian edition, dated February 26, 2026 (yes, future queen behavior, we don't question the calendar β¨). Mwah, love u, bye! π«Άπ
π¦ where this page comes from
- freebsd 15.1: base 15.1
- Copyright (c) 2002 M. Warner Losh <imp@FreeBSD.org>
- Copyright (c) 1999-2000 by Internet Software Consortium
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms