UDEVADM(8)

๐ŸŒธ UDEVADM(8) โ€” the udevadm manual, bestie edition ๐ŸŒธ

Ok so picture this: udevadm is the udev management tool. That's the whole vibe. It's the manual page for udevadm, and we're gonna read it together, mwah ๐Ÿ’–


โœจ NAME โœจ

udevadm โ€” udev management tool. That's it, that's the name, iconic behavior only ๐Ÿ‘‘


๐Ÿฆ‹ SYNOPSIS ๐Ÿฆ‹

udevadm [--debug] [--version] [--help]

udevadm info [options...] [devpath|syspath|id|unit...]

udevadm trigger [options...] [devpath|syspath|id|unit...]

udevadm settle [options...]

udevadm control options...

udevadm monitor [options...]

udevadm test [options...] devpath|syspath|id|unit

udevadm test-builtin [options...] command devpath|syspath|id|unit

udevadm verify [options...] [files...]

udevadm cat [options...] [files...]

udevadm wait [options...] devpath|syspath...

udevadm lock [options...] command...

Like, look at all those subcommands. She's versatile. She contains multitudes ๐Ÿ’…


๐ŸŒˆ DESCRIPTION ๐ŸŒˆ

So udevadm expects a command, right? And then command-specific options after it. She's the one who controls the runtime behavior of systemd-udevd, requests kernel events, manages the event queue, and hands you some simple debugging mechanisms on a little platter ๐ŸŽ€

Basically the backstage pass to your device situation. Obsessed tbh.


๐Ÿ’œ OPTIONS ๐Ÿ’œ

  • -d, --debug โ€” Print debug messages to standard error. Heads up: this option is implied in the udevadm test and udevadm test-builtin commands, so you don't gotta ask twice ๐Ÿซถ
  • -V, --version โ€” Print a short version string and dip. Bye โœŒ๏ธ
  • -h, --help โ€” Print a short help text and exit. The classic "help me I'm baby" move ๐Ÿ˜ญ

๐ŸŽ€ udevadm info [options...] [devpath|syspath|id|unit...] ๐ŸŽ€

This one queries the udev database for device information. Detective mode ๐Ÿ”

So the positional arguments are how you specify one or more devices, and ngl each one has rules:

  • it can be a device name โ€” but it must start with /dev/
  • or a sys path โ€” must start with /sys/
  • or a device ID โ€” like "n1", "c5:1", or "b259:1" (see sd_device_get_device_id(3))
  • or a systemd device unit name โ€” must end with .device (see systemd.device(5))

Rules are rules, bestie ๐Ÿ’…


๐ŸŒธ The options ๐ŸŒธ

  • -q, --query=TYPE โ€” Query the database for the specified type of device data. The valid TYPEs are: name, symlink, path, property, all. Pick your fighter.
  • --property=NAME โ€” When you're showing device properties with the --query=property option, this limits the display to just the properties named in the argument. The argument should be a comma-separated list of property names. If you don't specify it, all known properties get shown โ€” the full dump, no filter, chaotic but valid โœจ

Added in version 250.

  • --value โ€” When showing device properties with --query=property, this prints only their values, and skips the property name and the "=". Just the goods, no labels ๐ŸŽ
Careful bestie โ€” this cannot be used together with -x/--export or -P/--export-prefix. They do not get along.

Added in version 250.

  • -p, --path=DEVPATH โ€” The /sys/ path of the device to query, e.g. [/sys/]/class/block/sda. This option is an alternative to the positional argument with a /sys/ prefix. So udevadm info --path=/class/block/sda is equivalent to udevadm info /sys/class/block/sda. Same energy, different outfit ๐Ÿ’–
  • -n, --name=FILE โ€” The name of the device node or a symlink to query, e.g. [/dev/]/sda. This option is an alternative to the positional argument with a /dev/ prefix. So udevadm info --name=sda is equivalent to udevadm info /dev/sda. See what they did there ๐Ÿฆ‹
  • -r, --root โ€” Print absolute paths in name or symlink query. No shortcuts, full paths only.
  • -a, --attribute-walk โ€” Print all sysfs properties of the specified device that can be used in udev rules to match the specified device. It prints all devices along the chain, all the way up to the root of sysfs, that can be used in udev rules. It's giving family tree ๐Ÿงš

This switch supports JSON output mode (see --json= below). Note that because this switch generates multiple JSON objects, JSON-SEQ mode is automatically enabled (RFC7464). (Note: tools such as jq[1] natively support JSON-SEQ via the --seq switch.) Slay, standards-compliant behavior ๐Ÿ’…

  • -t, --tree โ€” Display a sysfs tree. This recursively iterates through the sysfs hierarchy and displays it in a tree structure. If a path is specified, only the subtree below it and its parent directories are shown. It shows both device and subsystem items. It's a whole aesthetic ๐ŸŒณ

Added in version 251.

  • -x, --export โ€” Print output as key/value pairs. Values are enclosed in single quotes. This takes effect only when --query=property or --device-id-of-file=FILE is specified. Conditional queen ๐Ÿ‘‘
  • -P, --export-prefix=NAME โ€” Add a prefix to the key name of exported values. This implies --export. Sneaky little implication, love that for us.
  • -d, --device-id-of-file=FILE โ€” Print major/minor numbers of the underlying device, where the file lives on. If this is specified, no positional arguments are accepted. Zero tolerance for extra args, periodt.
  • -e, --export-db โ€” Export the content of the udev database. The whole thing. Dump it ๐Ÿ˜ค
  • -c, --cleanup-db โ€” Cleanup the udev database. Tidy up, we're not living like this ๐Ÿงน
  • -w[SECONDS], --wait-for-initialization[=SECONDS] โ€” Wait for device to be initialized. If argument SECONDS is not specified, the default is to wait forever. FOREVER. No cap, forever-ever ๐Ÿซ 

Added in version 243.


๐ŸŒŸ The --export-db filter crew (added in version 255) ๐ŸŒŸ

These all do their thing "when used with --export-db" โ€” so they only show devices that match. Each one's got a job:

  • --subsystem-match[=SUBSYSTEM], --subsystem-nomatch[=SUBSYSTEM] โ€” When used with --export-db, only show devices of, or not of, the given subsystem respectively. Yes/no twin powers ๐ŸŽ€
  • --attr-match[=FILE[=VALUE]], --attr-nomatch[=FILE[=VALUE]] โ€” When used with --export-db, only show devices matching, or not matching, the given attribute respectively.
  • --property-match[=KEY=VALUE] โ€” When used with --export-db, only show devices matching the given property and value.
  • --tag-match[=TAG] โ€” When used with --export-db, only show devices with the given tag.
  • --sysname-match[=NAME] โ€” When used with --export-db, only show devices with the given "/sys" path.
  • --name-match[=NAME] โ€” When used with --export-db, only show devices with the given name in "/dev".
  • --parent-match[=NAME] โ€” When used with --export-db, only show devices with the given parent device. It's giving nepo baby but make it sysfs ๐Ÿ˜ญ
  • --initialized-match, --initialized-nomatch โ€” When used with --export-db, only show devices that are initialized, or not initialized, respectively.

๐Ÿฆ‹ Output-formatting options ๐Ÿฆ‹

  • --json=MODE โ€” Shows output formatted as JSON. Expects one of "short" (for the shortest possible output without any redundant whitespace or line breaks), "pretty" (for a pretty version of the same, with indentation and line breaks) or "off" (to turn off JSON output โ€” and this is the default). Pick your aesthetic โœจ
  • --no-pager โ€” Do not pipe output into a pager. Straight to your eyeballs, no middleman ๐Ÿ’€

๐Ÿ’– What the output looks like ๐Ÿ’–

The generated output shows the current device database entry in a terse format. Each line shown is prefixed with one of the following characters (this is the legend, memorize it, there will be a quiz):

  • "P:" โ€” Device path in /sys/
  • "M:" โ€” Device name in /sys/ (i.e. the last component of "P:")
  • "R:" โ€” Device number in /sys/ (i.e. the numeric suffix of the last component of "P:")
  • "J:" โ€” Device ID
  • "U:" โ€” Kernel subsystem
  • "B:" โ€” Driver subsystem
  • "T:" โ€” Kernel device type within subsystem
  • "D:" โ€” Kernel device node major/minor
  • "I:" โ€” Network interface index
  • "N:" โ€” Kernel device node name
  • "L:" โ€” Device node symlink priority
  • "S:" โ€” Device node symlink
  • "Q:" โ€” Block device sequence number (DISKSEQ)
  • "V:" โ€” Attached driver
  • "E:" โ€” Device property

Fifteen letters of pure information. We love a terse format ๐ŸŽ€


๐Ÿ”ฅ udevadm trigger [options...] [devpath|syspath|id|unit...] ๐Ÿ”ฅ

Request device events from the kernel. This is primarily used to replay events at system coldplug time. Very main character, very "let's run it back" ๐Ÿ”

It takes device specifications as positional arguments โ€” see the description of udevadm info above, same rules apply, no need to repeat myself (okay I would repeat myself but the manpage is being efficient).


โญ The options โญ

  • -v, --verbose โ€” Print the list of devices which will be triggered. A little preview, a little teaser ๐Ÿ‘€
  • -n, --dry-run โ€” Do not actually trigger the event. Fake it till you make it, but like, don't make it.
  • -q, --quiet โ€” Suppress error logging in triggering events. We're ignoring the drama today ๐Ÿ™ˆ

Added in version 248.

  • -t, --type=TYPE โ€” Trigger a specific type of devices. Valid types are "all", "devices", and "subsystems". The default value is "devices". Choose wisely ๐Ÿงš
  • -c, --action=ACTION โ€” Type of event to be triggered. Possible actions are "add", "remove", "change", "move", "online", "offline", "bind", and "unbind". Also, the special value "help" can be used to list the possible actions. The default value is "change". Eight actions plus a bonus helper โ€” she's generous ๐Ÿ’œ
  • --prioritized-subsystem=SUBSYSTEM[,SUBSYSTEM...] โ€” bestie, this one takes a comma-separated list of subsystems and gives them VIP treatment ๐ŸŽŸ๏ธ When events get triggered for devices, the devices from the subsystems you listed and their parents get triggered first. So if you do --prioritized-subsystem=block,net, then first up it's all the block devices and their parents, next all the network devices and their parents, and after that everyone else gets their turn. You can pass this option more than once and the lists just merge together, no drama โ€” so --prioritized-subsystem=block --prioritized-subsystem=net is literally equivalent to --prioritized-subsystem=block,net.

Added in version 251.

  • -s, --subsystem-match=SUBSYSTEM โ€” triggers events for devices that belong to a matching subsystem โœจ This one supports shell style pattern matching. Pass it multiple times and each matching result gets ORed โ€” meaning all the devices in each subsystem get triggered. Everyone's invited ๐Ÿ’…
  • -S, --subsystem-nomatch=SUBSYSTEM โ€” the opposite vibe ๐Ÿ’€ do not trigger events for devices in a matching subsystem. Also supports shell style pattern matching. Pass it multiple times and each matching result gets ANDed, so devices that don't match all the specified subsystems are the ones that get triggered.
  • -a, --attr-match=ATTRIBUTE=VALUE โ€” triggers events for devices with a matching sysfs attribute ๐Ÿฆ‹ If you give a value along with the attribute name, the content of the attribute is matched against your value using shell style pattern matching. If you give no value, then it just checks that the sysfs attribute exists. Specify this multiple times and each matching result is ANDed โ€” so only devices that have all the specified attributes get triggered. no gatekeeping, but also no skipping the checklist ๐Ÿ˜Œ
  • -A, --attr-nomatch=ATTRIBUTE=VALUE โ€” do not trigger events for devices with a matching sysfs attribute ๐Ÿ™ˆ Same deal: with a value, the attribute's content is matched against it using shell style pattern matching; without a value, it just checks whether the sysfs attribute exists. Multiple times = ANDed, so only devices that have none of the specified attributes get triggered.
  • -p, --property-match=PROPERTY=VALUE โ€” triggers events for devices with a matching property value ๐ŸŒธ Supports shell style pattern matching. Specify it more than once and each matching result is ORed, so devices that have one of the specified properties get triggered. very "if you're in any of these group chats you're coming to the party" energy.
  • -g, --tag-match=TAG โ€” triggers events for devices with a matching tag ๐ŸŽ€ Specify it multiple times and each matching result is ANDed โ€” devices must have all the specified tags to be triggered. the whole tag collection or nothing, bestie.
  • -y, --sysname-match=NAME โ€” triggers events for devices where the last component (i.e. the filename) of the /sys/ path matches the specified PATH ๐Ÿ‘‘ Supports shell style pattern matching. Specify it more than once and each matching result is ORed โ€” all devices that have any of the specified NAME get triggered.
  • --name-match=NAME โ€” triggers events for devices with a matching device path ๐ŸŒˆ Specify it more than once and each matching result is ORed, so all the specified devices get triggered.

Added in version 218.

  • -b, --parent-match=SYSPATH โ€” triggers events for all children of a given device ๐Ÿงš Specify it more than once and each matching result is ORed โ€” all children of each specified device get triggered. it's giving "bring your kids to work day".
  • --initialized-match, --initialized-nomatch โ€” the initialized-vibes duo ๐Ÿซถ

With --initialized-match, you trigger events for devices that are already initialized by systemd-udevd, and skip the ones that aren't initialized yet.

With --initialized-nomatch, it flips: trigger events for devices that are not initialized by systemd-udevd yet, and skip the ones that already are.

Typically it is essential that applications intending to use such a match make sure a suitable udev rule is installed that sets at least one property on devices that shall be matched ๐Ÿ’– See also the Initialized Devices section below for more details.

Warning โš ๏ธ --initialized-nomatch can potentially save a significant amount of time compared to re-triggering all devices in the system, and e.g. can be used to optimize boot time. However, this is not safe to be used in a boot sequence in general. Especially, when udev rules for a device depend on its parent devices (e.g. "ATTRS" or "IMPORT{parent}" keys, see udev(7) for more details), the final state of the device becomes easily unstable with this option. ๐Ÿ˜ญ like, genuinely, do not.

Added in version 251.

  • --include-parents โ€” triggers parent devices of found devices even if the parents won't match the filter condition ๐Ÿ‘€ This is useful if we're interested in limiting the coldplug activities to some devices or subsystems.

Added in version 258.

  • -w, --settle โ€” besides triggering events, this also waits for those events to finish โญ Note that this is different from calling udevadm settle. udevadm settle waits for all events to finish; this option only waits for events triggered by the same command to finish. read the fine print bestie, they are not the same girl ๐Ÿ’…

Added in version 238.

  • --uuid โ€” triggers the synthetic device events and associates a randomized UUID with each one ๐ŸŽŸ๏ธ These UUIDs are printed to standard output, one line for each event. They're included in the uevent environment block (in the "SYNTH_UUID=" property) and may be used to track delivery of the generated events. tracking numbers but make it udev โœจ

Added in version 249.

  • --wait-daemon[=SECONDS] โ€” before triggering uevents, wait for the systemd-udevd daemon to be initialized ๐Ÿฆ‹ Optionally takes a timeout value. Default timeout is 5 seconds. This is equivalent to invoking udevadm control --ping before udevadm trigger. polite little "u up?" before the party starts ๐Ÿ˜Œ

Added in version 241.

In addition, optional positional arguments can be used to specify device names or sys paths ๐Ÿ’– They must start with /dev/ or /sys/ respectively. no random paths, we have standards.


๐ŸŽ€ udevadm settle [options...]

Watches the udev event queue and exits if all current events are handled. it just sits there, watching, like your friend who refuses to leave until everyone's home safe ๐Ÿซถ

  • -t, --timeout=SECONDS โ€” maximum number of seconds to wait for the event queue to become empty. The default value is 120 seconds. A value of 0 will check if the queue is empty and always return immediately. A non-zero value will return an exit code of 0 if the queue became empty before the timeout was reached, non-zero otherwise โฐ
  • -E, --exit-if-exists=FILE โ€” stop waiting if FILE exists ๐Ÿ‘€ the literal "if you see this, we're done" flag.

See systemd-udev-settle.service(8) for more information.


๐Ÿ’… udevadm control options...

Modify the internal state of the running udev daemon. this is the remote-control era, bestie ๐ŸŽฎ

  • -e, --exit โ€” signal and wait for systemd-udevd to exit ๐Ÿšช No option except for --timeout can be specified after this option. Note that systemd-udevd.service contains Restart=always and so, as a result, this option restarts systemd-udevd. If you want to stop systemd-udevd.service, please use the following:
systemctl stop systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd-varlink.socket systemd-udevd.service

like, it will simply come back. it always comes back ๐Ÿ˜ญ

  • -l, --log-level=value โ€” set the internal log level of systemd-udevd ๐Ÿ”ฅ Valid values are the numerical syslog priorities or their textual representations: emerg, alert, crit, err, warning, notice, info, and debug.
  • -s, --stop-exec-queue โ€” signal systemd-udevd to stop executing new events. Incoming events will be queued ๐Ÿ“ฅ they're on hold, not cancelled.
  • -S, --start-exec-queue โ€” signal systemd-udevd to enable the execution of events โ–ถ๏ธ and we're back.
  • -R, --reload โ€” signal systemd-udevd to reload the rules files and other databases like the kernel module index ๐Ÿ”„ Reloading rules and databases does not apply any changes to already existing devices; the new configuration will only be applied to new events. no retroactive glow-ups, sorry ๐Ÿ’…
  • -p, --property=KEY=value โ€” set a global property for all events ๐ŸŒ
  • -m, --children-max=value โ€” set the maximum number of events systemd-udevd will handle at the same time. When 0 is specified, then the maximum is determined based on the system resources ๐Ÿงฎ let the system decide, she knows her limits.
  • --ping โ€” send a ping message to systemd-udevd and wait for the reply ๐Ÿ“ This may be useful to check that the systemd-udevd daemon is running. u up? text sent.

Added in version 241.

  • --trace=BOOL โ€” enable/disable trace logging in systemd-udevd ๐Ÿ”

Added in version 258.

  • --revert โ€” revert settings previously set with the udevadm control command ๐Ÿงผ When specified, settings set with -l/--log-level=, --trace, -m/--children-max=, and -p/--property= will be cleared. factory reset energy, but just for those.

Added in version 258.

  • -t, --timeout=seconds โ€” the maximum number of seconds to wait for a reply from systemd-udevd โณ
  • --load-credentials โ€” when specified, the following credentials are used when passed in ๐Ÿ“จ
    • udev.conf.* โ€” these credentials should contain valid udev.conf(5) configuration data. From each matching credential a separate file is created. Example: a passed credential udev.conf.50-foobar will be copied into a configuration file /run/udev/udev.conf.d/50-foobar.conf.

Added in version 256.

  • udev.rules.* โ€” these credentials should contain valid udev(7) rules. From each matching credential a separate file is created. Example: a passed credential udev.rules.50-foobar will be copied into a configuration file /run/udev/rules.d/50-foobar.rules.

Added in version 256.

Note, this does not imply the --reload option. So, if systemd-udevd is already running, please consider to also specify -reload to make the copied udev rules files used by systemd-udevd. ๐Ÿ‘‘ copying the file is not the same as telling her to read it, bestie.

Added in version 256.


๐ŸŒˆ udevadm monitor [options...]

Listens to the kernel uevents and events sent out by a udev rule and prints the devpath of the event to the console ๐Ÿ‘‚ It can be used to analyze the event timing, by comparing the timestamps of the kernel uevent and the udev event. literal event forensics ๐Ÿ”โœจ

  • -k, --kernel โ€” print the kernel uevents ๐Ÿง
  • -u, --udev โ€” print the udev event after the rule processing ๐ŸŽ€
  • -p, --property โ€” also print the properties of the event ๐Ÿ“‹
  • -s, --subsystem-match=string[/string] โ€” filters kernel uevents and udev events by subsystem (and optionally /devtype, like block/disk ๐ŸงŠ). Only events with a matching subsystem value get through. Specify it more than once and every matching result is ORed โ€” so it's like, "monitor all devices in all of these subsystems", bestie. More matches = more devices, no cap.
  • -t, --tag-match=string โ€” filters udev events by tag ๐Ÿท๏ธ. Only udev events with that tag attached pass. Specify it more than once and each matching result is ORed, so devices with any one of the specified tags are monitored. It's giving "OR logic, always" energy.

๐Ÿงช udevadm test [options...] devpath|syspath|id|unit

Simulates a udev event run for whatever device you hand it, and prints the debug output so you can peek behind the curtain ๐Ÿฆ‹. The --json= option is genuinely useful for parsing the final result. There's also an Example section, so scroll if you need inspo โœจ.

  • -a, --action=ACTION โ€” the type of event to simulate. Slay options include "add", "remove", "change", "move", "online", "offline", "bind", and "unbind". There's also the special value "help" which lists the possible actions for you, king behavior ๐Ÿ‘‘. The default value is "add".
  • -N, --resolve-names=early|late|never โ€” controls when udevadm should resolve the names of users and groups specified in udev rules ๐Ÿ’….
    • Set to early (the default) and names get resolved when the rules are parsed.
    • Set to late and names get resolved during the event being processed.
    • Set to never and names are never resolved โ€” and the relevant udev rules are ignored.
Careful with never, bestie โ€” those rules just do not run. ๐Ÿซถ

Added in version 209.

  • -D DIR, --extra-rules-dir=DIR โ€” also load udev rules files from the directory you specify ๐Ÿ“‚. This option can be specified multiple times. It's lowkey perfect for debugging udev rules: copy some rules files to a temporary directory, edit them, and point this option at it. Files found in the specified directories have a higher priority than rules files in the default udev/rules.d directories used by systemd-udevd. See udev(7) for more details about the search paths.

Added in version 258.

  • -v, --verbose โ€” shows verbose logs while processing udev rules. Yes, more words, but the useful words ๐Ÿ”ฅ.

Added in version 258.

  • --json=MODE โ€” shows output formatted as JSON ๐ŸŽ€. Expects one of:
    • "short" โ€” the shortest possible output, no redundant whitespace or line breaks.
    • "pretty" โ€” the pretty version of the same, with indentation and line breaks.
    • "off" โ€” turns JSON output off. This is the default.

๐Ÿงฑ udevadm test-builtin [options...] command devpath|file|unit

Runs a built-in command COMMAND for device DEVPATH, and prints debug output ๐ŸŒธ.

  • -a, --action=ACTION โ€” type of event to simulate, same menu as before: "add", "remove", "change", "move", "online", "offline", "bind", and "unbind". And yeah, "help" lists all the possible actions ๐Ÿ’–. The default value is "add".

Added in version 250.


๐Ÿ” udevadm verify [options...] [files...]

Checks udev rules files for syntactic, semantic, and stylistic correctness ๐Ÿงš. Like a vibe check, but for files.

The positional arguments can specify one or more files to check. Each argument must be an absolute path to a udev rules file, or a directory that contains rules files, or just a file name of a udev rules file (e.g. 99-systemd.rules). If you give a file name, it'll be searched in the udev/rules.d directories that are processed by systemd-udevd โ€” and if it's not found there, it gets searched in the current working directory. If you specify no files at all, the udev rules are read from the files located in those same udev/rules.d directories that systemd-udevd processes. See udev(7) for more details about the search paths ๐Ÿฆ‹.

The exit status is 0 if all specified udev rules files are syntactically, semantically, and stylistically correct โ€” and a non-zero error code otherwise ๐Ÿ’€.

  • -N, --resolve-names=early|late|never โ€” when to resolve names of users and groups specified in udev rules.
    • early (the default) โ€” names resolved when the rules are parsed.
    • late โ€” names will not be verified, since systemd-udevd resolves names during each event being processed.
    • never โ€” names are never resolved and the relevant rules are ignored.

Added in version 254.

  • --root=PATH โ€” when looking for udev rules files in the udev/rules.d directories, operate on files underneath the specified root path PATH ๐Ÿ“. And if you gave a file name that isn't found in the udev/rules.d directories, it gets searched in the specified root path PATH instead of the current working directory.

Added in version 254.

  • --no-summary โ€” do not show the summary. Short and sweet ๐Ÿ“.

Added in version 254.

  • --no-style โ€” ignore style issues ๐ŸŽ€. When specified, even if style issues are found in the udev rules files, the exit status is 0 as long as no syntactic or semantic errors are found. Style is optional, correctness is not, iykyk.

Added in version 254.


๐Ÿˆ udevadm cat [options...] [file...]

Shows udev rules files or udev.conf ๐ŸŒˆ. It's literally cat, but with taste.

The positional arguments can specify one or more files to show. Each argument must be an absolute path to a udev rules file, or a directory that contains rules files, or a file name of a udev rules file (e.g. 99-systemd.rules). Give a file name and it'll be searched in the udev/rules.d directories processed by systemd-udevd, then in the current working directory if not found. Specify no files and the udev rules get read from the files located in the same udev/rules.d directories that systemd-udevd processes. See udev(7) for more details about the search paths โœจ.

  • --root=PATH โ€” when looking for udev rules files in the udev/rules.d directories, operate on files underneath the specified root path PATH. When a file name is specified and it isn't found in the udev/rules.d directories, the file gets searched in the specified root path PATH, rather than the current working directory ๐Ÿ“‚.

Added in version 258.

  • --tldr โ€” only prints the "interesting" parts of the configuration files ๐Ÿ‘€, skipping comments and empty lines, plus section headers that are followed only by comments and empty lines. TL;DR mode: activated.

Added in version 258.

  • --config โ€” shows udev.conf(5) files rather than udev rules files ๐Ÿ’…. When specified, no udev rules file cannot be specified.

Added in version 258.


โณ udevadm wait [options...] devpath|syspath...

Waits for devices (or device symlinks) to be created and initialized by systemd-udevd ๐Ÿซถ. Every device path has to start with "/dev/" or "/sys/", like these iconic examples:

"/dev/sda"
"/dev/disk/by-path/pci-0000:3c:00.0-nvme-1-part1"
"/sys/devices/pci0000:00/0000:00:1f.6/net/eth0"
"/sys/class/net/eth0"

It can take multiple devices at once, bestie ๐Ÿ’–. This is super useful for waiting on devices being processed by systemd-udevd after, say, partitioning or formatting them.

  • -t, --timeout=SECONDS โ€” max number of seconds to wait for the specified devices or device symlinks to be created, initialized, or removed โฑ๏ธ. The default value is "infinity".

Added in version 251.

  • --initialized=BOOL โ€” check whether systemd-udevd initialized the devices. Defaults to true โœ…. When false, the command only checks whether the specified devices exist. Set this to false if there are no udev rules for the specified devices, because in that case the devices will never be considered initialized ๐Ÿ˜ญ. See the Initialized Devices section below for more details.

Added in version 251.

  • --removed โ€” the command waits for devices being removed instead of created or initialized ๐Ÿ™ˆ. If this is specified, --initialized= will be ignored.

Added in version 251.

  • --settle โ€” also watches the udev event queue, and waits for all queued events to be processed by systemd-udevd ๐ŸŒธ.

Added in version 251.


๐Ÿ”’ udevadm lock [options...] command...

udevadm lock takes an (advisory) exclusive lock on a block device โ€” or on all the specified devices โ€” as per Locking Block Device Access[2], and then invokes a program with the locks taken ๐Ÿ‘‘. When the invoked program exits, the locks are automatically released and its return value is propagated as the exit code of udevadm lock. Clean. Effortless. Iconic.

This tool is especially useful for making sure systemd-udevd.service(8) doesn't probe a block device while you're changing it โ€” for example, creating partitions or formatting file systems ๐Ÿ”ฅ. Ngl, lots of tools that interface with block devices natively support taking the relevant locks โ€” see for example sfdisk(8)'s --lock switch.

The command expects at least one block device specified via --device= or --backing=, plus a command line to execute as arguments.

  • --device=DEVICE, -d DEVICE โ€” takes a path to a device node of the device to lock ๐Ÿ”. This switch may be used multiple times (and in combination with --backing=) to lock multiple devices. If you specify a partition block device node, the containing "whole" block device is automatically determined and used for the lock, as per the specification. If multiple devices are specified, they get deduplicated, sorted by the major/minor of their device nodes, and then locked in order. This switch must be used at least once to specify at least one device to lock. (Alternatively, use --backing=, see below.)

Added in version 251.

  • --backing=PATH, -b PATH โ€” if you give it a path to a device node, it's identical to --device= ๐Ÿ’…. But this switch alternatively accepts a path to a regular file or directory, in which case the block device of the file system that file/directory resides on is automatically determined and used as if it had been specified with --device=. Sneaky, but make it work.

Added in version 251.

  • --timeout=SECS, -t SECS โ€” how long to wait at most until all locks can be taken โฐ. Takes a value in seconds, or in the usual supported time units โ€” see systemd.time(7). If specified as zero, the lock is attempted and if it's not successful the invocation immediately fails. If passed as "infinity" (the default), the invocation waits indefinitely until the lock can be acquired. If the lock can't be taken within the specified time, the specified command will not be executed and the invocation will fail ๐Ÿ’€.

Added in version 251.

  • --print, -p โ€” okay bestie, this is the โ€œdonโ€™t actually lock anythingโ€ mode: instead of locking the specified devices and executing a command, it just prints the device paths that would be locked and executes no command. Itโ€™s lowkey useful for determining the โ€œwholeโ€ block device when a partition block device is specified. The devices come out sorted by their device node major number as the primary ordering key and the minor number as the secondary ordering key (so theyโ€™re shown in the order theyโ€™d be locked). Heads up: the number of lines printed here can be less than the number of --device= and --backing= switches specified, because some of those can resolve to the same โ€œwholeโ€ devices. โœจ Added in version 251.

๐Ÿงš INITIALIZED DEVICES ๐Ÿงš

Initialized devices are the ones where at least one udev rule already finished executing โ€” for any action but "remove" โ€” and that rule set a property or other device setting (which means it has an entry in the udev device database). If a "remove" action is seen for them, theyโ€™re no longer considered initialized, because that removes their entry in the udev device database. Also, important: devices that have no udev rules are never considered initialized, but they might still be announced via the sd-device API (or similar). No cap. ๐Ÿ’…

๐ŸŒธ EXAMPLE ๐ŸŒธ

Example 1. Format a File System

Take a lock on the backing block device while creating a file system, to ensure that systemd-udevd does not probe or announce the new superblock before it is comprehensively written:

# udevadm lock --device=/dev/sda1 mkfs.ext4 /dev/sda1

Example 2. Format a RAID File System

Similar, but take locks on multiple devices at once:

# udevadm lock --device=/dev/sda1 --device=/dev/sdb1 mkfs.btrfs /dev/sda1 /dev/sdb1

Example 3. Copy in a File System

Take a lock on the backing block device while copying in a prepared file system image, to ensure that systemd-udevd does not probe or announce the new superblock before it is fully written:

# udevadm lock -d /dev/sda1 dd if=fs.raw of=/dev/sda1

Example 4. Predict Network Interface Renaming

To predict a network interface name, udevadm test can be used:

$ udevadm test /sys/class/net/wlan0 --json=pretty 2>/dev/null | jq .networkInterface.name
"wlp59s0"

To predict symbolic links to a device node, udevadm test can be used:

$ udevadm test /dev/nvme0n1p1 --json=pretty 2>/dev/null | jq .node.symlinks
[
  "/dev/disk/by-diskseq/1-part1",
  "/dev/disk/by-id/nvme-WDC_PC_SN720_SDAQNTW-512G-1001_192290802247-part1",
  "/dev/disk/by-id/nvme-WDC_PC_SN720_SDAQNTW-512G-1001_192290802247_1-part1",
  "/dev/disk/by-id/nvme-eui.1922908022470001001b448b44ccb9d6-part1",
  "/dev/disk/by-path/pci-0000:3c:00.0-nvme-1-part/by-partnum/1",
  "/dev/disk/by-path/pci-0000:3c:00.0-nvme-1-part1"
]
$ udevadm test /dev/input/event3 --json=pretty 2>/dev/null | jq .node.symlinks
[
  "/dev/input/by-path/platform-i8042-serio-0-event-kbd"
]

๐Ÿ’– SEE ALSO ๐Ÿ’–

Bestie homework: go check out udev(7), systemd-udevd.service(8), and udev.conf(5). ๐Ÿซถ

๐Ÿ“ NOTES ๐Ÿ“

  1. jq โ€” https://jqlang.github.io/jq/manual/
  2. Locking Block Device Access โ€” https://systemd.io/BLOCK_DEVICE_LOCKING

๐Ÿ’– Footer check, bestie: systemd 261.3 is the source/version, UDEVADM(8) is the page, and the date is doing its little mystery era โ€” it wasnโ€™t in the footer line we got, but the vibes are eternal. Mwah, go be the main character of device management. ๐ŸŽ€

๐Ÿ“ฆ where this page comes from