Help us shape the future of Go! Take the 2026 Go Developer Survey

go-udev

module
v0.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2026 License: GPL-3.0

README

go-udev GitHub Repo stars

Go Report Card Build Status Linters Status Coverage Status GoDoc Release License

Simple udev implementation in Golang developed from scratch. This library allow to listen and manage Linux-kernel (since version 2.6.10) Netlink messages to user space (ie: NETLINK_KOBJECT_UEVENT).

Like udev you will be able to monitor, display and manage devices plug to the system.

Monitoring requires a Linux kernel: on other platforms the module still builds and the uevent parsing/matching API stays available, but UEventConn methods return netlink.ErrNotSupported.

How to

Get sources

Use the library:

go get github.com/pilebones/go-udev

Or install the command line tool:

go install github.com/pilebones/go-udev/cmd/go-udev@latest

The library itself has no external dependency.

Unit test
go test ./...
Compile
go build ./cmd/go-udev
Usage
./go-udev -<mode> [-file=<absolute_path>]

Allowed mode: info or monitor File should contains matcher rules (see: "Advanced usage" section)

Info Mode

Crawl /sys/devices uevent struct to detect plugged devices:

./go-udev -info
Monitor Mode

Handle all kernel message to detect change about plugged or unplugged devices:

./go-udev -monitor

Only the events sent by the kernel or by udevd are delivered, the others are dropped and reported as netlink.ErrUntrustedSender: an uevent is trivial to forge for a process able to write on the socket, and consumers usually act on the devices it announces.

Examples

Example of output when a USB storage is plugged:

2017/10/20 23:47:23 Handle UEvent{Action: add, KObj: /devices/pci0000:00/0000:00:14.0/usb1/1-1, Env: {ACTION="add", BUSNUM="001", DEVNAME="bus/usb/001/005", DEVNUM="005", DEVPATH="/devices/pci0000:00/0000:00:14.0/usb1/1-1", DEVTYPE="usb_device", MAJOR="189", MINOR="4", PRODUCT="58f/6387/10b", SEQNUM="2511", SUBSYSTEM="usb", TYPE="0/0/0"}}
2017/10/20 23:47:23 Handle UEvent{Action: add, KObj: /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0, Env: {ACTION="add", DEVPATH="/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0", DEVTYPE="usb_interface", INTERFACE="8/6/80", MODALIAS="usb:v058Fp6387d010Bdc00dsc00dp00ic08isc06ip50in00", PRODUCT="58f/6387/10b", SEQNUM="2512", SUBSYSTEM="usb", TYPE="0/0/0"}}
2017/10/20 23:47:23 Handle UEvent{Action: add, KObj: /module/usb_storage, Env: {ACTION="add", DEVPATH="/module/usb_storage", SEQNUM="2513", SUBSYSTEM="module"}}
[...]

Example of output when a USB storage is unplugged:

[...]
2017/10/20 23:47:29 Handle UEvent{Action: remove, KObj: /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/host4/target4:0:0/4:0:0:0/block/sdb, Env: {ACTION="remove", DEVNAME="sdb", DEVPATH="/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/host4/target4:0:0/4:0:0:0/block/sdb", DEVTYPE="disk", MAJOR="8", MINOR="16", SEQNUM="2543", SUBSYSTEM="block"}}
[...]
2017/10/20 23:47:29 Handle UEvent{Action: remove, KObj: /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0, Env: {ACTION="remove", DEVPATH="/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0", DEVTYPE="usb_interface", INTERFACE="8/6/80", MODALIAS="usb:v058Fp6387d010Bdc00dsc00dp00ic08isc06ip50in00", PRODUCT="58f/6387/10b", SEQNUM="2548", SUBSYSTEM="usb", TYPE="0/0/0"}}
2017/10/20 23:47:29 Handle UEvent{Action: remove, KObj: /devices/pci0000:00/0000:00:14.0/usb1/1-1, Env: {ACTION="remove", BUSNUM="001", DEVNAME="bus/usb/001/005", DEVNUM="005", DEVPATH="/devices/pci0000:00/0000:00:14.0/usb1/1-1", DEVTYPE="usb_device", MAJOR="189", MINOR="4", PRODUCT="58f/6387/10b", SEQNUM="2549", SUBSYSTEM="usb", TYPE="0/0/0"}}

Note: To implement your own monitoring system, please see cmd/go-udev/main.go as a simple example.

Advanced usage

Is it possible to filter uevents/devices with a Matcher.

A Matcher is a list of your own rules to match only relevant uevent kernel message (see: matcher.sample).

You could pass this file using for both mode:

./go-udev -file  matcher.sample [...]

Library usage

Monitoring stops as soon as the context is cancelled, and the queue is closed when the worker returns:

conn := new(netlink.UEventConn)
if err := conn.Connect(netlink.UdevEvent); err != nil {
	log.Fatalln("unable to subscribe to netlink uevent, err:", err)
}
defer conn.Close()

ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()

queue, errs := make(chan netlink.UEvent), make(chan error)
go conn.MonitorWithContext(ctx, queue, errs, nil) // pass a netlink.Matcher to filter the events

for {
	select {
	case uevent, more := <-queue:
		if !more {
			return
		}
		log.Println("handle", uevent.Action, uevent.KObj)
	case err := <-errs:
		// Reading errors are not fatal, a dropped message does not stop the monitoring
		log.Println("ERROR:", err)
	}
}

Docker usage

How to build docker image
docker build . -t go-udev
How to execute go-udev -info using docker image
docker run --rm -t go-udev -info
How to execute go-udev -monitor using docker image
docker run --rm -v=/dev:/dev -v /run/udev:/run/udev:ro --net=host -t go-udev -monitor

Warning: unsafe method because we share host /dev directory to the container.

TODO: unsafe and -monitor is not fully functional in docker, fix working in progress...

Troubleshooting

Don't hesitate to notice if you detect a problem with this tool or library.

Documentation

License

go-udev is available under the GNU GPL v3 - Clause License.

Directories

Path Synopsis
cmd
go-udev command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL