Support My Work!
austins research
austins research
Discord
  • Preamble
  • About austins research
    • About my tooling
    • austins research services
  • Project Specific Research
    • Feasibility Analysis: Open-Source Discord Bot Platform with No-Code Builder and Advanced Dashboard
    • Automating Discord Server Membership Upon Auth0 Authentication
  • News Research
    • Gemini Report - Shapes Inc Issue
  • Physics Research
    • Page 1
  • Dislang Related Research
    • Dislang Research
    • Assessing the Feasibility of a Dedicated Discord API Programming Language
    • Designing a Domain-Specific Language for Discord API Interaction
  • Gemini Deep Research
    • using UDEV to make a dead man switch
    • SMTP Email Explained
    • AI: Reality or Misinturpritation?
    • Creating a custom Discord Server Widget
    • Cloudflare Pages & Static Blogging
    • Firebase, Supabase, PocketBase Comparison
    • A Comparative Analysis of Large and Small Language Models
    • Building a Privacy-Focused, End-to-End Encrypted Communication Platform: A Technical Blueprint
    • Architecting a Multi-Tenant Managed Redis-Style Database Service on Kubernetes
    • Building an Open-Source DNS Filtering SaaS: A Technical Blueprint
    • Leveraging Automated Analysis, Checks, and AI for C++ to Rust Codebase Migration
    • Constructing Automated Code Translation Systems: Principles, Techniques, and Challenges
    • Universal Webhook Ingestion and JSON Standardization: An Architectural Guide
  • The Investigatory Powers Act 2016: Balancing National Security and Individual Liberties in the Digit
  • The e-Devlet Kapısı Gateway: Breaches, Fallout, and the Erosion of Digital Trust in Turkey
  • Evolving the Discord Ecosystem
Powered by GitBook
LogoLogo

Support Me

  • My Coinbase Link
  • By subscribing to my blog
  • Support Page
  • Apply to join the Community

Stuff About me

  • My Blog
  • my website :)
  • My brain site
  • Privacy Statement
  • Terms of Service

Company Plugging

  • AWFixer Foundation
  • AWFixer Tech
  • AWFixer Development
  • AWFixer Industries
  • AWFixer and Friends
  • AWFixer Shop

© 2025 austin and contributers

On this page
  • Triggering Actions on USB Drive Removal in Linux using udev
  • 1. Introduction
  • 2. The udev Subsystem and Device Events
  • 3. Writing udev Rules for Device Removal
  • 4. Identifying the Specific USB Drive
  • 5. Executing Actions with RUN+=
  • 6. Rule Management and Debugging
  • 7. Execution Environment and Advanced Topics
  • 8. Alternative Methods
  • 9. Conclusion and Best Practices

Was this helpful?

Export as PDF
  1. Gemini Deep Research

using UDEV to make a dead man switch

Triggering Actions on USB Drive Removal in Linux using udev

1. Introduction

Modern Linux systems rely heavily on the udev subsystem to manage hardware devices dynamically. udev operates in userspace, responding to events generated by the Linux kernel when devices are connected (hot-plugged) or disconnected.1 Its primary functions include creating and removing device nodes in the /dev directory, managing device permissions, loading necessary kernel modules or firmware, and providing stable device naming through symbolic links.1

A common system administration task involves automating actions based on hardware state changes. This report details the standard and recommended method for initiating a command or script specifically when an external USB drive is removed or becomes undetected by the system. This process leverages the event-driven nature of udev by creating custom rules that match the removal event for a specific device and execute a predefined action.

2. The udev Subsystem and Device Events

The kernel notifies the udev daemon (systemd-udevd.service on modern systems) of hardware changes via uevents.2 Upon receiving a uevent, the udev daemon processes a set of rules to determine the appropriate actions.2 These rules, stored in specific directories, allow administrators to customize device handling.2

Key directories for udev rules include:

  • /usr/lib/udev/rules.d/: Contains default system rules provided by packages. These should generally not be modified directly.2

  • /etc/udev/rules.d/: The standard location for custom, administrator-defined rules. Rules here take precedence over files with the same name in /usr/lib/udev/rules.d/.2

  • /run/udev/rules.d/: Used for volatile runtime rules, typically managed dynamically.5

udev processes rules files from these directories collectively, sorting them in lexical (alphabetical) order regardless of their directory of origin.3 This ordering is critical, as later rules can modify properties set by earlier rules, unless explicitly prevented.3 Files are typically named using a numerical prefix (e.g., 10-, 50-, 99-) followed by a descriptive name and the .rules suffix (e.g., 70-persistent-net.rules, 99-my-usb.rules).3 The numerical prefix directly controls the order of execution.4

3. Writing udev Rules for Device Removal

3.1. Rule Syntax Basics

udev rules consist of one or more key-value pairs separated by commas. A single rule must be written on a single line, as udev does not support line continuation characters for rule definitions (though some sources incorrectly suggest backslashes might work, standard practice and documentation emphasize single-line rules).3 Lines starting with # are treated as comments.3

Each rule contains:

  • Match Keys: Conditions that must be met for the rule to apply to a given device event. Common operators are == (equality) and != (inequality).3

  • Assignment Keys: Actions to be taken or properties to be set when the rule matches. Common operators are = (assign value), += (add to a list), and := (assign final value, preventing further changes).3

A rule is applied only if all its match keys evaluate to true for the current event.3

3.2. Matching Removal Events (ACTION=="remove")

To trigger a command specifically upon device removal, the primary match key is ACTION=="remove".1 This key matches the uevent generated when the kernel detects a device has been disconnected.

To further refine the match, other keys are typically used:

  • SUBSYSTEM / SUBSYSTEMS: This filters events based on the kernel subsystem the device belongs to.

    • SUBSYSTEM=="usb" targets the event related to the USB device interface itself.1

    • SUBSYSTEM=="block" targets events related to the block device node (e.g., /dev/sda, /dev/sdb1) created for USB storage devices.9

    • SUBSYSTEMS== (plural) can match the subsystem of the device or any of its parent devices in the sysfs hierarchy. This is often necessary when matching attributes of a parent device (like a USB hub or controller) from the context of a child device (like the block device node).4 The choice between usb and block (or others like tty for serial devices) depends on the specific event and device level the action should be tied to. For actions related to the storage volume itself (like logging its removal based on UUID), SUBSYSTEM=="block" is often appropriate.

  • Identifier Matching (using ENV{...}): Crucially, when a device is removed (ACTION=="remove"), its attributes stored in the sysfs filesystem are often no longer accessible because the corresponding sysfs entries are removed along with the device.1 Therefore, matching based on ATTR{key} or ATTRS{key} (which query sysfs) typically fails for remove events.1

    Instead, udev preserves certain device properties discovered during the add event in its internal environment database. These properties can be matched during the remove event using the ENV{key}=="value" syntax.1 Common environment variables available during removal include ENV{ID_VENDOR_ID}, ENV{ID_MODEL_ID}, ENV{PRODUCT}, ENV{ID_SERIAL}, ENV{ID_FS_UUID}, ENV{ID_FS_LABEL}, etc..1 The exact available keys should be verified using udevadm monitor --property while removing the target device.1

A basic template for a removal rule therefore looks like:

ACTION=="remove", SUBSYSTEM=="<subsystem>", ENV{<identifier_key>}=="<identifier_value>", RUN+="/path/to/action"

3.3. Rule Order and Data Availability

The lexical processing order of .rules files is not merely about precedence for overriding settings; it directly impacts the availability of information, particularly the environment variables (ENV{...}) needed for remove event matching.3

System-provided rules, often located in /usr/lib/udev/rules.d/ with lower numerical prefixes (e.g., 50-udev-default.rules, 60-persistent-storage.rules), perform initial device probing during the add event.3 These rules are responsible for querying device attributes and populating the udev environment database with keys like ID_FS_UUID, ID_VENDOR_ID, ID_SERIAL_SHORT, etc..18

A custom rule designed to match a remove event based on an environment variable (e.g., ENV{ID_FS_UUID}=="...") can only succeed if that variable has already been set by a preceding rule during the device's lifetime (specifically, during the add event processing). Consequently, custom rules that depend on these environment variables must have a filename that sorts lexically after the system rules that populate them. Using a prefix like 70-, 90-, or 99- is common practice to ensure the custom rule runs late enough in the sequence for the necessary ENV data to be available.5 Placing such a rule too early (e.g., 10-my-rule.rules) might cause it to fail silently because the ENV variable it attempts to match has not yet been defined by the system rules.

4. Identifying the Specific USB Drive

Triggering an action on the removal of any USB device is rarely desirable. The udev rule must be specific enough to target only the intended drive. Several identifiers can be used, primarily accessed via ENV{...} keys during a remove event.

4.1. Available Identifiers and Tools

  • Vendor and Product ID:

    • Identifies the device model (e.g., SanDisk Cruzer Blade).

    • Obtained using lsusb 23 or udevadm info (look for idVendor, idProduct in ATTRS during add, or ID_VENDOR_ID, ID_MODEL_ID, PRODUCT in ENV during add/remove).1

    • Matching (Remove): ENV{ID_VENDOR_ID}=="vvvv", ENV{ID_MODEL_ID}=="pppp", or ENV{PRODUCT}=="vvvv/pppp/rrrr".1

    • Limitation: Not unique if multiple identical devices are used.6

  • Serial Number:

    • Often unique to a specific physical device instance.

    • Obtained using udevadm info -a -n /dev/sdX (look for ATTRS{serial} in parent device attributes during add).19 May appear as ID_SERIAL or ID_SERIAL_SHORT in ENV during add/remove.9

    • Matching (Remove): ENV{ID_SERIAL}=="<serial_string>" or ENV{ID_SERIAL_SHORT}=="<short_serial>".17 The exact format varies.

    • Limitation: Some devices lack unique serial numbers, or report identical serials for multiple units.24

  • Filesystem UUID:

    • Unique identifier assigned to a specific filesystem format on a partition.

    • Obtained using blkid (e.g., sudo blkid -c /dev/null) 22 or udevadm info (look for ID_FS_UUID in ENV).18

    • Matching (Remove): ENV{ID_FS_UUID}=="<filesystem_uuid>".18

    • Requirement: Rule file must have a numerical prefix greater than the system rules that generate this variable (e.g., >60).18

    • Persistence: Stable across reboots and different USB ports.

    • Limitation: Changes if the partition is reformatted.22 Only applies to block devices with recognizable filesystems.

  • Filesystem Label:

    • User-assigned, human-readable name for a filesystem.

    • Obtained using blkid 22 or udevadm info (look for ID_FS_LABEL in ENV).22

    • Matching (Remove): ENV{ID_FS_LABEL}=="<filesystem_label>".22

    • Limitation: Easily changed by the user, not guaranteed to be unique, less reliable than UUID.

  • Partition UUID/Label (GPT):

    • Identifiers stored in the GUID Partition Table (GPT) itself, associated with the partition entry rather than the filesystem within it.

    • Obtained using blkid or udevadm info (look for ID_PART_ENTRY_UUID, ID_PART_ENTRY_NAME in ENV).22

    • Matching (Remove): ENV{ID_PART_ENTRY_UUID}=="<part_uuid>" or ENV{ID_PART_ENTRY_NAME}=="<part_label>".22

    • Persistence: More persistent than filesystem identifiers across reformats, as they are part of the partition table structure.22

    • Limitation: Only applicable to drives using GPT partitioning.

  • Device Path (DEVPATH):

    • The device's path within the kernel's sysfs hierarchy.

    • Obtained via udevadm info.

    • Limitation: Unstable; can change based on which USB port is used or the order devices are detected.1 Not recommended for reliable identification across sessions.

4.2. Tools for Finding Identifiers

  • lsusb: Primarily used to list connected USB devices and their Vendor/Product IDs.23 lsusb -v provides verbose output.

  • blkid: Specifically designed to list block devices and their associated filesystem UUIDs and Labels.18 Using sudo blkid -c /dev/null ensures fresh information by bypassing the cache.26

  • udevadm info: A versatile tool for querying the udev database and device attributes.

    • udevadm info -a -n /dev/sdX (or other device node like /dev/ttyUSB0): Displays a detailed hierarchy of attributes (ATTRS{...}) and stored environment variables (E:... or ENV{...}) for the specified device and its parents.9 This is useful for finding potential identifiers during an add event.

    • udevadm monitor --property --udev (or --kernel --property): Monitors uevents in real-time and prints the associated environment variables.1 This is essential for determining exactly which ENV{...} keys and values are available during the ACTION=="remove" event for the target device.

4.3. Comparison of Identification Methods for Removal Events

Choosing the best identifier depends on the specific requirements, particularly the need for uniqueness and persistence, and what information the device actually provides. The Filesystem UUID or Partition UUID (for GPT) are often the most reliable for storage devices if reformatting is infrequent. If multiple identical devices without unique serial numbers are used, identification can be challenging.24

Identifier Type

How to Obtain (Commands)

Uniqueness Level

Persistence (Reboot/Port/Reformat)

Availability for ACTION=="remove" (Example ENV Key)

Pros

Cons

Vendor/Product ID

lsusb, udevadm info

Model

Yes / Yes / Yes

ENV{ID_VENDOR_ID}, ENV{ID_MODEL_ID}, ENV{PRODUCT}

Simple, widely available

Not unique for multiple identical devices 6

Serial Number

udevadm info (ATTRS{serial})

Device (Often)

Yes / Yes / Yes

ENV{ID_SERIAL}, ENV{ID_SERIAL_SHORT}

Unique per physical device (usually)

Not always present or unique 24, format varies

Filesystem UUID

blkid, udevadm info

Filesystem

Yes / Yes / No

ENV{ID_FS_UUID}

Reliable, unique per filesystem

Changes on reformat 22, requires rule >60 18, storage only

Filesystem Label

blkid, udevadm info

User Assigned

Yes / Yes / No

ENV{ID_FS_LABEL}

Human-readable

Not guaranteed unique, easily changed, storage only

Partition UUID/Label

blkid, udevadm info

Partition (GPT)

Yes / Yes / Yes

ENV{ID_PART_ENTRY_UUID}, ENV{ID_PART_ENTRY_NAME}

Persistent across reformats 22

GPT only

5. Executing Actions with RUN+=

The RUN assignment key specifies a program or script to be executed when the rule's conditions are met.1 Using RUN+= allows multiple commands (potentially from different matching rules) to be added to a list for execution, whereas RUN= would typically overwrite previous assignments and execute only the last one specified.4

5.1. Syntax and Path Considerations

Commands should be specified with their absolute paths (e.g., /bin/echo, /usr/local/bin/my_script.sh). The execution environment for udev scripts is minimal and does not typically include standard user PATH settings.13 Relying on relative paths or command names without paths will likely lead to failure.

Examples:

  • RUN+="/bin/touch /tmp/usb_removed_flag" 12

  • RUN+="/usr/bin/logger --tag usb-removal Device with UUID $env{ID_FS_UUID} removed" 18

  • RUN+="/usr/local/bin/handle_removal.sh"

5.2. Passing Information to Scripts

udev provides substitution mechanisms to pass event-specific information as arguments to the RUN script.3 This allows the script to know which device triggered the event. Common substitutions include:

  • %k: The kernel name of the device (e.g., sdb1).8

  • %n: The kernel number of the device (e.g., 1 for sdb1).8

  • %N or $devnode: The path to the device node in /dev (e.g., /dev/sdb1).9

  • $devpath: The device's path in the sysfs filesystem.18

  • %E{VAR_NAME} or $env{VAR_NAME}: The value of a udev environment variable. This is crucial for accessing identifiers during remove events (e.g., $env{ID_FS_UUID}, %E{ACTION}).9

  • %%: A literal % character.8

  • $$: A literal $ character.8

Example passing arguments:

RUN+="/usr/local/bin/notify_removal.sh %E{ACTION} %k $env{ID_FS_UUID}"

This would execute the script /usr/local/bin/notify_removal.sh with three arguments: the action ("remove"), the kernel name (e.g., "sdb1"), and the filesystem UUID of the removed device.

5.3. Complete Example Rule

Combining identification and execution, a rule to run a script upon removal of a specific USB drive identified by its filesystem UUID might look like this:

Code snippet

# /etc/udev/rules.d/99-usb-drive-removal.rules
# Trigger script when USB drive with specific UUID is removed
ACTION=="remove", SUBSYSTEM=="block", ENV{ID_FS_UUID}=="1234-ABCD", RUN+="/usr/local/bin/handle_usb_removal.sh %k $env{ID_FS_UUID}"

Explanation:

  • # /etc/udev/rules.d/99-usb-drive-removal.rules: Specifies the file location and name. The 99- prefix ensures it runs late, after system rules have likely populated ENV{ID_FS_UUID}.6

  • ACTION=="remove": Matches only device removal events.1

  • SUBSYSTEM=="block": Matches events related to block devices (like /dev/sdXN).18

  • ENV{ID_FS_UUID}=="1234-ABCD": Matches only if the removed block device has the specified filesystem UUID (replace 1234-ABCD with the actual UUID).18

  • RUN+="/usr/local/bin/handle_usb_removal.sh %k $env{ID_FS_UUID}": Executes the specified script, passing the kernel name (%k) and the filesystem UUID ($env{ID_FS_UUID}) as arguments.12

6. Rule Management and Debugging

Properly managing, applying, and debugging udev rules is essential for successful implementation.

6.1. Applying Rule Changes

After creating or modifying a rule file in /etc/udev/rules.d/, the udev daemon needs to be informed of the changes.

  • Reloading Rules: The command sudo udevadm control --reload-rules instructs the udev daemon to re-read all rule files from the configured directories.2 While some sources suggest udev might detect changes automatically 1, explicitly reloading is the standard and recommended practice. Importantly, reloading rules does not automatically apply the new logic to devices that are already connected.1

  • Triggering Rules: To apply the newly loaded rules to existing devices without physically unplugging and replugging them, use sudo udevadm trigger.6 This command simulates events for current devices, causing udev to re-evaluate the ruleset against them. Often, reload and trigger are combined: sudo udevadm control --reload-rules && sudo udevadm trigger.9

  • Restarting udev: While sometimes suggested (sudo service udev restart or sudo systemctl restart systemd-udevd.service) 6, this is often unnecessary and more disruptive than reload and trigger.30 However, in some cases, particularly involving script execution permissions or environment issues, a full restart might resolve problems that reload/trigger do not.21

  • Physical Reconnection: For testing add and remove rules specifically, the simplest way to ensure the rules are evaluated under normal conditions is often to disconnect and reconnect the physical device after reloading the rules.32

6.2. Testing and Verification Tools

  • udevadm test: This command simulates udev event processing for a specific device without actually executing RUN commands or making persistent changes.5 It shows which rules are being read, which ones match the simulated event, and what actions would be taken. This is invaluable for debugging rule syntax and matching logic. The device is specified by its sysfs path. Example: sudo udevadm test $(udevadm info -q path -n /dev/sdb1).14 Note that on some systems, the path might need to be specified differently (e.g., /sys/block/sdb/sdb1).18

  • udevadm monitor: This tool listens for and prints kernel uevents and udev events as they happen in real-time.1 Using the --property flag is crucial, as it displays the environment variables associated with each event.1 Running sudo udevadm monitor --property --udev while removing the target USB drive is the definitive way to verify that the remove event is detected and to see the exact ENV{key}=="value" pairs available for matching.

6.3. Debugging Strategies

  • Isolate the Problem: Start with the simplest possible rule to confirm basic event detection works (e.g., ACTION=="remove", SUBSYSTEM=="usb", RUN+="/bin/touch /tmp/remove_triggered"). If this works, incrementally add the specific identifiers (ENV{...}) and then the actual script logic.12

  • Check System Logs: Examine system logs for errors related to udev or the executed script. Use journalctl -f -u systemd-udevd.service or check files like /var/log/syslog or /var/log/messages.33 Increase logging verbosity for detailed debugging: sudo udevadm control --log-priority=debug.33

  • Log from the Script: Since RUN scripts don't output to a terminal 28, add explicit logging within the script itself. Redirect output to a file in a location where the udev process (running as root) has write permissions (e.g., /tmp or /var/log). Example line in a shell script: echo "$(date): Script triggered for device $1 with UUID $2" >> /tmp/my_udev_script.log.28 Ensure the script itself is executable (chmod +x).13

  • Verify Permissions: Check file permissions: the rule file in /etc/udev/rules.d/ should typically be owned by root and readable.6 The script specified in RUN+= must be executable.13 The script also needs appropriate permissions to perform its intended actions (e.g., write to log files, interact with services).21

  • Check Syntax: Meticulously review the rule syntax: commas between key-value pairs, correct operators (== for matching, = or += for assignment), proper quoting, and ensure the entire rule is on a single line.3 Use udevadm test to help identify syntax errors.18

7. Execution Environment and Advanced Topics

Understanding the context in which RUN+= commands execute is critical to avoid common pitfalls.

7.1. RUN+= Limitations

Scripts launched via RUN+= operate under significant constraints:

  • Short Lifespan: udev is designed for rapid event processing. To prevent stalling the event queue, processes initiated by RUN+= are expected to terminate quickly. udev (or systemd managing it) will often forcefully kill tasks that run for more than a few seconds.1 This makes RUN+= unsuitable for long-running processes, daemons, or tasks involving significant delays.

  • Restricted Environment: The execution environment is minimal and isolated. Scripts do not inherit the environment variables, session information (like DISPLAY or DBUS_SESSION_BUS_ADDRESS), or shell context of any logged-in user.17 This means directly launching GUI applications or using tools like notify-send will typically fail.17 The PATH variable is usually very limited, necessitating the use of absolute paths for all commands.17 Access to network resources might also be restricted.9

  • Filesystem and Permissions Issues: While scripts usually run as the root user, they operate within a restricted context, potentially affected by security mechanisms like SELinux or AppArmor. Direct filesystem operations like mounting or unmounting within a RUN+= script are strongly discouraged; they often fail due to udev's use of private mount namespaces and the short process lifespan killing helper processes (like FUSE daemons).1 In some scenarios, the filesystem might appear read-only to the script unless the udev service is fully restarted.21 Writing to user home directories using ~ will fail; absolute paths must be used.28

The fundamental reason for these limitations stems from udev's core purpose: it is an event handler focused on rapid device configuration, not a general-purpose process manager.1 Allowing complex, long-running tasks within udev's event loop would compromise system stability and responsiveness, especially during critical phases like boot-up.1 Therefore, udev imposes these restrictions to ensure it can fulfill its primary role efficiently.

7.2. Workaround for Long-Running Tasks: systemd Integration

For tasks that exceed the limitations of RUN+= (e.g., require network access, run for extended periods, need user context, perform complex filesystem operations), the recommended approach is to delegate the work to systemd.1

The strategy involves using the udev rule merely as a trigger to start a dedicated systemd service unit. The service unit then executes the actual script or command in a properly managed environment outside the constraints of the udev event processing loop.1

Mechanism:

  1. Create a systemd Service Unit: Define a service file (e.g., /etc/systemd/system/my-usb-handler@.service). The @ symbol indicates a template unit, allowing instances to be created with parameters (like the device name). This service file specifies the command(s) to run, potentially setting user/group context, dependencies, and resource limits. Alternatively, a user service can be created in ~/.config/systemd/user/ to run tasks within a specific user's context.9

  2. Modify the udev Rule: Change the RUN+= directive to simply start the systemd service instance, passing any necessary information (like the kernel device name %k) as part of the instance name. Example udev rule: ACTION=="remove", SUBSYSTEM=="block", ENV{ID_FS_UUID}=="1234-ABCD", RUN+="/bin/systemctl start my-usb-handler@%k.service" 1

This approach cleanly separates the rapid event detection (udev) from the potentially longer-running task execution (systemd), leveraging the strengths of each component and avoiding udev timeouts.1

7.3. Troubleshooting Common Pitfalls

  • Rule Ordering Dependencies: As discussed previously, ensure rule files have appropriate numerical prefixes (e.g., 90- or higher) if they rely on ENV variables set by earlier system rules.5

  • Multiple Trigger Events: A single physical device connection or removal can generate multiple uevents for different layers of the device stack (e.g., the USB device itself, the SCSI host adapter, the block device /dev/sdx, and each partition /dev/sdxN).9 If a rule is not specific enough, the RUN script might execute multiple times for one physical action. To prevent this, make the rule more specific, for instance by matching only a specific partition number (KERNEL=="sd?1", ATTR{partition}=="1") or device type (ENV{DEVTYPE}=="partition").18

  • ENV vs. ATTRS Naming: Remember that the keys used for matching environment variables (ENV{ID_VENDOR_ID}) might differ slightly from the keys used for matching sysfs attributes (ATTRS{idVendor}).1 Always use udevadm monitor --property during a remove event to confirm the exact ENV key names available.1

8. Alternative Methods

While udev is the standard and generally preferred method for reacting to device events in Linux, alternative approaches exist:

  • Custom Polling Daemons/Scripts: A background process can be written to periodically check for the presence or absence of the target device. This could involve checking for specific entries in /dev/disk/by-uuid/ or /dev/disk/by-id/, or parsing the output of commands like lsusb or blkid at regular intervals.12

    • Pros: Complete control over logic.

    • Cons: Inefficient (polling vs. event-driven), requires manual process management, potentially complex.

  • udisks/udisksctl: This is a higher-level service built on top of udev and other components, often used by desktop environments for managing storage devices, including automounting.1 It provides a D-Bus interface and the udisksctl monitor command can be used to watch for device changes.26

    • Pros: Richer feature set (mounting, power management), desktop integration.

    • Cons: Can be overkill, potentially complex setup 1, often tied to active user sessions.1

  • Kernel Hotplug Helper (Legacy): An older mechanism where the kernel could be configured (via /proc/sys/kernel/hotplug) to directly execute a specified userspace script upon uevents.35

    • Pros: Direct kernel invocation.

    • Cons: Largely superseded by the more flexible udev system, less common now.

  • Direct sysfs Manipulation: For testing purposes, one can simulate removal by unbinding the driver (echo <bus-id> > /sys/bus/usb/drivers/usb/unbind) 36 or potentially disabling power to a specific USB port if the hardware supports it (echo suspend > /sys/bus/usb/devices/.../power/level), though support for the latter is inconsistent.36 These are not practical monitoring solutions.

Table 2: High-Level Comparison: udev vs. Alternatives for USB Removal Actions

Method

Mechanism

Primary Use Case

Complexity (Setup/Maint.)

Efficiency

Flexibility

Integration (System/Desktop)

Recommendation Status

udev Rules

Event-driven

Standard device event handling

Moderate

High

High

Core System

Recommended

Custom Polling Daemon

Polling

Custom monitoring logic

High

Low

High

Manual

Situational

udisks/udisksctl

Event-driven

Desktop storage mgmt, automounting

Moderate to High

High

Moderate

Desktop/System Service

Situational

Kernel Hotplug Helper (Legacy)

Event-driven

Direct kernel event handling

Moderate

High

Low

Kernel

Legacy

For most scenarios involving triggering actions on device removal, udev provides the most efficient, flexible, and standard mechanism integrated into the core Linux system.

9. Conclusion and Best Practices

The udev subsystem provides a robust and event-driven framework for executing commands or scripts when a specific USB drive is removed from a Linux system. By crafting precise rules that match the ACTION=="remove" event and identify the target device using persistent identifiers stored in the udev environment (ENV{...} keys), administrators can reliably automate responses to device disconnection.

Key Best Practices:

  1. Use Reliable Identifiers: Prefer ENV{ID_FS_UUID}, ENV{ID_PART_ENTRY_UUID}, or ENV{ID_SERIAL_SHORT} (if unique and available) for identifying the specific drive during remove events. Verify the exact key names and values using udevadm monitor --property during device removal.1

  2. Correct Rule Placement and Naming: Place custom rules in /etc/udev/rules.d/. Use a high numerical prefix (e.g., 90-, 99-) for rules matching ENV variables to ensure they run after system rules that populate these variables.3

  3. Use Absolute Paths: Always specify the full, absolute path for any command or script invoked via RUN+=.13

  4. Keep RUN Scripts Simple: RUN+= scripts should be lightweight and terminate quickly. Avoid complex logic, long delays, network operations, or direct filesystem mounting/unmounting within the udev rule itself.1

  5. Delegate Complex Tasks: For any non-trivial actions, use the udev rule's RUN+= command solely to trigger a systemd service unit. Let systemd manage the execution of the actual task in a suitable environment.1

  6. Test Thoroughly: Utilize udevadm test to verify rule syntax and matching logic, and udevadm monitor to observe real-time events and environment variables.1

  7. Implement Logging: Add logging within any script triggered by udev to aid in debugging, ensuring output is directed to a file writable by the root user (e.g., in /tmp or /var/log).28

By adhering to these practices, administrators can effectively leverage udev to create reliable and sophisticated automation workflows triggered by USB device removal events on Linux systems.

Works cited

PreviousDesigning a Domain-Specific Language for Discord API InteractionNextSMTP Email Explained

Last updated 1 month ago

Was this helpful?

udev - ArchWiki, accessed April 12, 2025,

22 Dynamic Kernel Device Management with udev - SUSE Documentation, accessed April 12, 2025,

Writing udev rules - Daniel Drake, accessed April 12, 2025,

Linux udev rules - Downtown Doug Brown, accessed April 12, 2025,

Why do the rules in udev/.../rules.d have numbers in front of them - Unix & Linux Stack Exchange, accessed April 12, 2025,

Udev Rules — ROS Tutorials 0.5.2 documentation - Clearpath Robotics, accessed April 12, 2025,

Are numbers necessary for some config/rule file names? - Unix & Linux Stack Exchange, accessed April 12, 2025,

blog-raw/_posts/2013-11-24-udev-rule-cheatsheet.md at master - GitHub, accessed April 12, 2025,

How to Execute a Shell Script When a USB Device Is Plugged | Baeldung on Linux, accessed April 12, 2025,

How do I use udev to run a shell script when a USB device is removed? - Stack Overflow, accessed April 12, 2025,

Udev Rules - Clearpath Robotics Documentation, accessed April 12, 2025,

How to detect a USB drive removal and trigger a udev rule? : r/linuxquestions - Reddit, accessed April 12, 2025,

using udev rules create and remove device node on a kernel module load and unload, accessed April 12, 2025,

Udev Rules — ROS Tutorials 0.5.2 documentation - Clearpath Robotics, accessed April 12, 2025,

Simple UDEV rule to run a script when a chosen USB device is removed - GitHub, accessed April 12, 2025,

systemd udev Rules to Detect USB Device Plugging (including Bus and Device Number), accessed April 12, 2025,

Using udev rules to run a script on USB insertion - linux - Super User, accessed April 12, 2025,

Use UUID in udev rules and mount usb drive on /media/$UUID - Super User, accessed April 12, 2025,

writing udev rule for USB device - Ask Ubuntu, accessed April 12, 2025,

Getting udev to recognize unique usb drives from a set - with the same uuid and labels? RHEL7, accessed April 12, 2025,

Udev does not have permissions to write to the file system - Stack Overflow, accessed April 12, 2025,

How to get udev to identify a USB device regardless of the USB port it is plugged in?, accessed April 12, 2025,

How to list all USB devices - Linux Audit, accessed April 12, 2025,

Help identifying and remapping usb device names : r/linux4noobs - Reddit, accessed April 12, 2025,

How to uniquely identify a USB device in Linux - Super User, accessed April 12, 2025,

Operating on disk devices - Unix Memo - Read the Docs, accessed April 12, 2025,

linux - How do I figure out which /dev is a USB flash drive? - Super User, accessed April 12, 2025,

Cannot run script using udev rules - Unix & Linux Stack Exchange, accessed April 12, 2025,

Can't execute script from udev rule [closed] - Ask Ubuntu, accessed April 12, 2025,

What is the correct way to restart udev? - Ask Ubuntu, accessed April 12, 2025,

Reloading udev rules fails - ubuntu - Super User, accessed April 12, 2025,

Refresh of udev rules directory does not work - Ask Ubuntu, accessed April 12, 2025,

How to reload udev rules after nixos rebuild switch? - Help, accessed April 12, 2025,

USB device configuration: Alternative to udev - Robots For Roboticists, accessed April 12, 2025,

usb connection event on linux without udev or libusb - Stack Overflow, accessed April 12, 2025,

Is there a command that's equivalent to physically unplugging a usb device?, accessed April 12, 2025,

Disable usb port [duplicate] - udev - Ask Ubuntu, accessed April 12, 2025,

https://wiki.archlinux.org/title/Udev
https://documentation.suse.com/sles/12-SP5/html/SLES-all/cha-udev.html
https://www.reactivated.net/writing_udev_rules.html
https://www.downtowndougbrown.com/2014/03/linux-udev-rules/
https://unix.stackexchange.com/questions/204979/why-do-the-rules-in-udev-rules-d-have-numbers-in-front-of-them
https://www.clearpathrobotics.com/assets/guides/melodic/ros/Udev%20Rules.html
https://unix.stackexchange.com/questions/730861/are-numbers-necessary-for-some-config-rule-file-names
https://github.com/blindFS/blog-raw/blob/master/_posts/2013-11-24-udev-rule-cheatsheet.md
https://www.baeldung.com/linux/shell-run-script-usb-plugged
https://stackoverflow.com/questions/31055611/how-do-i-use-udev-to-run-a-shell-script-when-a-usb-device-is-removed
https://docs.clearpathrobotics.com/docs/ros1noetic/ros/ros/tutorials/ros101/intermediate/udev_rules/
https://www.reddit.com/r/linuxquestions/comments/1h7h4ek/how_to_detect_a_usb_drive_removal_and_trigger_a/
https://stackoverflow.com/questions/40673336/using-udev-rules-create-and-remove-device-node-on-a-kernel-module-load-and-unloa
https://www.clearpathrobotics.com/assets/guides/kinetic/ros/Udev%20Rules.html
https://github.com/samuel-engel/execute-on-usb-remove
https://phip1611.de/blog/systemd-udev-rules-to-detect-usb-device-plugging/
https://superuser.com/questions/305723/using-udev-rules-to-run-a-script-on-usb-insertion
https://superuser.com/questions/521402/use-uuid-in-udev-rules-and-mount-usb-drive-on-media-uuid
https://askubuntu.com/questions/1021547/writing-udev-rule-for-usb-device
https://superuser.com/questions/1492647/getting-udev-to-recognize-unique-usb-drives-from-a-set-with-the-same-uuid-and
https://stackoverflow.com/questions/49182368/udev-does-not-have-permissions-to-write-to-the-file-system
https://unix.stackexchange.com/questions/299388/how-to-get-udev-to-identify-a-usb-device-regardless-of-the-usb-port-it-is-plugge
https://linux-audit.com/hardware/faq/how-to-list-all-usb-devices/
https://www.reddit.com/r/linux4noobs/comments/1bk7wdn/help_identifying_and_remapping_usb_device_names/
https://superuser.com/questions/983399/how-to-uniquely-identify-a-usb-device-in-linux
https://unix-memo.readthedocs.io/en/latest/devices.html
https://superuser.com/questions/361885/how-do-i-figure-out-which-dev-is-a-usb-flash-drive
https://unix.stackexchange.com/questions/119078/cannot-run-script-using-udev-rules
https://askubuntu.com/questions/967398/cant-execute-script-from-udev-rule
https://askubuntu.com/questions/82470/what-is-the-correct-way-to-restart-udev
https://superuser.com/questions/311940/reloading-udev-rules-fails
https://askubuntu.com/questions/1292062/refresh-of-udev-rules-directory-does-not-work
https://discourse.nixos.org/t/how-to-reload-udev-rules-after-nixos-rebuild-switch/18442
https://www.robotsforroboticists.com/usb-device-configuration/
https://stackoverflow.com/questions/22157797/usb-connection-event-on-linux-without-udev-or-libusb
https://unix.stackexchange.com/questions/669370/is-there-a-command-thats-equivalent-to-physically-unplugging-a-usb-device
https://askubuntu.com/questions/1057384/disable-usb-port