How to Enable or Disable USB Storage Devices on Linux with Shell Scripting

Controlling access to USB storage devices is a foundational practice for maintaining data integrity and preventing unauthorized data exfiltration in enterprise environments. As threats from removable media persist—ranging from insider data leaks to malware-laden USB drives—IT administrators and Managed Service Providers (MSPs) must enforce strict policies on USB usage. One effective and scalable method is scripting control at the kernel module level. This blog post dives deep into a robust shell script designed to enable, disable, or configure USB storage devices on Linux with shell scripting.

Background

On Linux systems, USB storage access is governed by kernel modules—specifically, usb-storage and uas (USB Attached SCSI). These modules can be automatically loaded when devices are connected (implicit loading) or manually invoked (explicit loading). By blocking or permitting these modules at the system level, IT professionals can effectively control USB storage device behavior across fleets of Linux endpoints.

The script in question is built for automation, policy enforcement, and compatibility with RMM platforms like NinjaOne. It creates and manages configuration files in /etc/modprobe.d/, updates the initial RAM filesystem (initramfs), and can optionally trigger a system reboot—making it a complete solution for USB device governance.

The Script:

#!/usr/bin/env bash

# Description: Enable or disable USB storage devices on Linux.
# By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
# Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
# Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
# Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
# Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
# Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
# Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
# EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#
#   There are two methods of loading USB storage drivers that allow mounting of USB storage devices:
#       1. Implicit loading: The USB storage driver is loaded automatically when a USB storage device is connected.
#       2. Explicit loading: The USB storage driver is loaded manually by a user, program, or script.
#
# Release Notes: Initial Release
#
# Notes: This will create config files in /etc/modprobe.d/ as needed to block USB storage devices.
#
# Usage: [-Enable | -Disable] [-Reboot]
#
# Preset Parameter: --help
#   Displays the help menu.
#
# Preset Parameter: -Enable
#   Enables USB storage devices.
#
# Preset Parameter: -Disable
#   Disables USB storage devices.
#
# Preset Parameter: -Reboot
#   Reboots the system, if needed, after enabling or disabling USB storage devices.

# Functions
# Print an error message and exit with a specific status code
die() {
    local _ret="${2:-1}"
    test "${_PRINT_HELP:-no}" = yes && print_help >&2
    echo "$1" >&2
    exit "${_ret}"
}

print_help() {
    printf '\n\n%s\n\n' 'Usage: [-Enable | -Disable]'
    printf '  %s\n' '-Enable'
    printf '    Enables USB storage devices'
    printf '  %s\n' '-Disable'
    printf '    Disables USB storage devices'
}

# Set the default values
_arg_reboot="false"

# Parse the command-line arguments
parse_commandline() {
    while test $# -gt 0; do
        _key="$1"
        case "$_key" in
        -Enable | --Enable | -enable | --enable | -e | --e)
            _arg_action="Enable"
            ;;
        -Disable | --Disable | -disable | --disable | -d | --d)
            _arg_action="Disable"
            ;;
        --Reboot | --reboot | -Reboot | -reboot | -r | --r)
            _arg_reboot="true"
            ;;
        --help | -help | -h | --h)
            _PRINT_HELP=yes die "" 0
            ;;
        *)
            _PRINT_HELP=yes die "[Error] Got an unexpected argument '$1'" 1
            ;;
        esac
        shift
    done
}

parse_commandline "$@"

# Exit if not running as root
if [[ $EUID -ne 0 ]]; then
    die "[Error] This script must be run as root or SYSTEM from NinjaRMM" 1
fi

# If script form variables are used, replace the command line parameters with their value.
if [[ -n "${action}" ]] && [[ "${action}" == "Enable" ]]; then
    _arg_action="Enable"
elif [[ -n "${action}" ]] && [[ "${action}" == "Disable" ]]; then
    _arg_action="Disable"
fi

if [[ "${reboot}" == "true" ]]; then
    _arg_reboot="true"
fi

# Check if action is empty
if [[ -z "${_arg_action}" ]]; then
    die "Invalid action. Use Enable or Disable" 1
fi

# Variables
# Modprobe.d folder
modprobFolder="/etc/modprobe.d"
# Config file
configFile="${modprobFolder}/ninja-usb-block.conf"

# Check if modprobe.d folder does not exists
if ! [ -d "${modprobFolder}" ]; then
    die "[Error] Modprobe folder does not exist" 1
fi

# Check if usb-storage and uas kenel drivers are modules
if ! modprobe -n uas >/dev/null 2>&1; then
    die "[Error] USB Attached SCSI driver(uas) must be compiled as a kernel module" 1
fi
if ! modprobe -n usb-storage >/dev/null 2>&1; then
    die "[Error] USB storage(usb-storage) driver must be compiled as a kernel module" 1
fi

if [[ "${_arg_action}" == "Enable" ]]; then
    # Enable USB storage

    # Check if our file exists
    if [ -f "${configFile}" ]; then
        echo "[Info] Enabling USB storage devices"
        # Remove our config file
        rm "${configFile}"
        echo "[Info] Enabled USB storage devices"
    else
        echo "[Info] USB storage devices are already enabled"
    fi

    # Remove other blocks USB storage in other files
    for file in "${modprobFolder}"/*; do
        # Remove implicit USB Storage block
        if grep -q "blacklist usb_storage" "${file}"; then
            echo "[Info] Removing implicit USB Storage block in ${file}"
            sed -i '/blacklist usb_storage/d' "${file}"
            echo "[Info] Removed implicit USB Storage block in ${file}"
        fi
        # Remove implicit USB Attached SCSI block
        if grep -q "blacklist uas" "${file}"; then
            echo "[Info] Removing implicit USB Attached SCSI block in ${file}"
            sed -i '/blacklist uas/d' "${file}"
            echo "[Info] Removed implicit USB Attached SCSI block in ${file}"
        fi
        # Remove explicit USB Storage driver block
        if grep -q "install usb-storage /bin/true" "${file}"; then
            echo "[Info] Removing explicit USB Storage block in ${file}"
            sed -i '/install usb-storage \/bin\/true/d' "${file}"
            echo "[Info] Removed explicit USB Storage block in ${file}"
        fi
        # Remove explicit USB Attached SCSI driver block
        if grep -q "install uas /bin/true" "${file}"; then
            echo "[Info] Removing explicit USB Attached SCSI block in ${file}"
            sed -i '/install uas \/bin\/true/d' "${file}"
            echo "[Info] Removed explicit USB Attached SCSI block in ${file}"
        fi
    done

    # Check that update-initramfs command exists
    if command -v update-initramfs >/dev/null 2>&1; then
        # Update the initramfs
        echo "[Info] Updating initramfs"
        update-initramfs -u >/dev/null 2>&1
        echo "[Info] Updated initramfs"
    fi

    if [[ "${_arg_reboot}" == "true" ]]; then
        echo "[Info] Rebooting the system to enable USB storage devices"
        # Shutdown in 1 minute
        shutdown -r +1
    else
        echo "[Info] USB storage devices are enabled, please reboot the system"
    fi

elif [[ "${_arg_action}" == "Disable" ]]; then
    # Disable USB storage

    # Variables to determine if we should block the drivers
    blacklist_uas="false"
    blacklist_usb_storage="false"
    block_uas="false"
    block_usb_storage="false"

    # Check if usb_storage or uas is blocked in other files
    for file in "${modprobFolder}"/*; do

        # Check if implicit loading is already blocked
        if grep -q "blacklist uas" "${file}"; then
            echo "[Info] USB Attached SCSI drivers are already implicitly blocked in ${file}"
        else
            blacklist_uas="true"
        fi

        # Check if implicit loading is already blocked
        if grep -q "blacklist usb_storage" "${file}"; then
            echo "[Info] USB storage drivers are already implicitly blocked in ${file}"
        else
            blacklist_usb_storage="true"
        fi

        # Check if explicit loading is already blocked
        if grep -q "install uas /bin/true" "${file}"; then
            echo "[Info] USB Attached SCSI drivers are already explicitly blocked in ${file}"
        else
            block_uas="true"
        fi

        # Check if explicit loading is already blocked
        if grep -q "install uas /bin/true" "${file}"; then
            echo "[Info] USB storage drivers are already explicitly blocked in ${file}"
        else
            block_usb_storage="true"
        fi
    done

    if [ "${blacklist_uas}" == "true" ]; then
        echo "[Info] Implicitly Disabling USB Attached SCSI driver"

        # Check if config file exists
        if ! [ -f "${configFile}" ]; then
            echo "[Info] Creating blocklist config file (${configFile})"
            touch "${configFile}"
        fi

        # Write the line to the file
        echo "blacklist uas" >>"${configFile}"
    fi

    if [ "${blacklist_usb_storage}" == "true" ]; then
        echo "[Info] Implicitly Disabling USB storage driver"

        # Check if config file exists
        if ! [ -f "${configFile}" ]; then
            echo "[Info] Creating blocklist config file (${configFile})"
            touch "${configFile}"
        fi

        # Write the line to the file
        echo "blacklist usb_storage" >>"${configFile}"
    fi

    if [ "${block_uas}" == "true" ]; then
        echo "[Info] Explicitly Disabling USB Attached SCSI driver"

        # Check if uas config file exists
        if ! [ -f "${modprobFolder}" ]; then
            echo "[Info] Creating UAS config file (${modprobFolder}/uas.conf)"
            touch "${modprobFolder}/uas.conf"
        fi

        # Write the line to the file
        echo "install uas /bin/true" >>"${modprobFolder}/uas.conf"
    fi

    if [ "${block_usb_storage}" == "true" ]; then
        echo "[Info] Explicitly Disabling USB storage driver"

        # Check if usb-storage config file exists
        if ! [ -f "${modprobFolder}" ]; then
            echo "[Info] Creating USB storage config file (${modprobFolder}/usb-storage.conf)"
            touch "${modprobFolder}/usb-storage.conf"
        fi

        # Write the line to the file
        echo "install usb-storage /bin/true" >>"${modprobFolder}/usb-storage.conf"
    fi

    # Unload the modules
    echo "[Info] Unloading USB storage modules"
    modprobe -r uas >/dev/null 2>&1
    modprobe -r usb_storage >/dev/null 2>&1
    rmmod uas >/dev/null 2>&1
    rmmod usb_storage >/dev/null 2>&1

    # Check if the modules are still loaded
    modules_unloaded="true"
    if lsmod | grep -q uas; then
        modules_unloaded="false"
    fi
    if lsmod | grep -q usb_storage; then
        modules_unloaded="false"
    fi

    # Check that update-initramfs command exists
    if command -v update-initramfs >/dev/null 2>&1; then
        # Update the initramfs
        echo "[Info] Updating initramfs"
        update-initramfs -u >/dev/null 2>&1
        echo "[Info] Updated initramfs"

        # Set to false so we can reboot or warn that a reboot is needed
        modules_unloaded="false"
        if [[ "${_arg_reboot}" == "false" ]]; then
            echo "[Warn] USB storage devices can still be mounted, please reboot the system"
        fi
    fi

    if [ "${modules_unloaded}" == "true" ]; then
        echo "[Info] Unloaded USB storage modules"
    else
        if [[ "${_arg_reboot}" == "true" ]]; then
            echo "[Info] USB storage devices are still mounted, rebooting the system"
            # Shutdown in 1 minute
            shutdown -r +1
        else
            echo "[Warn] USB storage devices are still mounted, please unmount them and rerun this script OR reboot the system"
        fi
    fi

else
    die "[Error] Invalid parameter. Use -Enable or -Disable" 1
fi

 

Detailed Breakdown

Here’s how the script functions step-by-step:

1. Command-Line Parsing

The script accepts the following flags:

  • -Enable: Allows USB storage by removing related kernel module restrictions.
  • -Disable: Prevents USB storage by applying kernel module blacklists and explicit loading blocks.
  • -Reboot: Optional flag to reboot the machine after the change.
  • –help: Displays usage instructions.

2. Privilege Check

The script verifies it’s being run with root privileges—essential for kernel-level changes.

3. Module Detection

It confirms that usb-storage and uas are compiled as kernel modules, a prerequisite for the changes to be effective.

4. Enabling USB Storage

When -Enable is invoked:

  • The script removes its own config file (ninja-usb-block.conf).
  • It scans other .conf files in /etc/modprobe.d/ and deletes any blacklist or explicit load-block directives.
  • It regenerates initramfs to reflect the changes.
  • Optionally, it schedules a reboot.

5. Disabling USB Storage

When -Disable is used:

  • The script writes blacklist (blacklist usb_storage, blacklist uas) and install block (install usb-storage /bin/true) directives into dedicated .conf files.
  • It forcibly unloads the kernel modules using modprobe -r and rmmod.
  • It validates module removal via lsmod.
  • It updates initramfs and, if needed, reboots the system.

Potential Use Cases

Case Study: Securing Developer Laptops

An MSP managing Linux developer workstations wants to prevent code or proprietary data from being exfiltrated via USB drives. Using NinjaOne, the admin deploys this shell script with the -Disable -Reboot flags. All targeted systems become USB-storage restricted upon next boot. During a code freeze, USB access is temporarily re-enabled via a scheduled task with -Enable.

This method ensures tight control with auditability and rollback capability.

Comparisons

Method Pros Cons
udev rules Granular device control Requires device IDs, complex
Group Policy (on Windows) Native enforcement Not applicable to Linux
Shell Script (This) Fast, scriptable, integrates well Requires kernel module support
SELinux/AppArmor Very secure Complex to configure properly

Compared to alternatives, this shell script offers a balanced mix of simplicity, portability, and system-wide enforcement without needing to handle device IDs or third-party software.

FAQs

Q1: What happens if my system doesn’t use initramfs?

The script silently skips initramfs updates. However, changes may not apply until the next reboot.

Q2: Can this script be deployed through NinjaOne?

Yes. It’s fully compatible with NinjaOne’s Linux scripting automation, including support for passing parameters like action=Disable and reboot=true.

Q3: What if a user manually loads the module after disabling?

The install /bin/true directive prevents even manual module loading unless explicitly removed.

Q4: Is this reversible?

Absolutely. Running the script with -Enable undoes all configuration and restores USB functionality.

Implications

Using this script enhances endpoint security and enforces policy compliance across Linux machines. It mitigates risks from:

  • Insider threats transferring sensitive data
  • Malware infection from rogue USBs
  • Bypass of DLP systems via removable drives

For regulated industries like finance, healthcare, or government, this script offers an effective compliance control.

Recommendations

  • Test before mass deployment—especially on systems with custom kernel modules.
  • Automate rollback procedures—store a backup of modified .conf files.
  • Integrate with RMM alerts—track systems where USB storage is re-enabled.
  • Schedule reboots carefully to avoid disrupting users.

Final Thoughts

Whether you’re looking to disable USB storage devices on Linux with shell scriptingenable USB storage devices on Linux with shell scripting, or configure USB storage access policies on Linux, this script offers a reliable and maintainable approach. Through NinjaOne’s scripting and automation framework, MSPs and IT professionals can operationalize USB governance at scale—enforcing security policies while maintaining administrative control.

For managing Linux endpoints efficiently and securely, NinjaOne’s centralized scripting, automation, and reporting tools complement this script’s power, helping teams scale enforcement without increasing workload.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service delivery tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

How to Use Shell Scripting to Synchronize the Time on Linux

How to Check USB Storage Status in Linux Using Shell Scripting

How to Enable or Disable USB Storage Devices on Linux with Shell Scripting

How to Synchronize Time on macOS with Shell Scripting

How to Monitor macOS Performance Data with Shell Scripting

How to Force a Time Synchronization Using PowerShell

×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
  • Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
  • Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
  • Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).