Why sudo Loses Your PATH on Linux and How to Keep It

How to keep your PATH when using sudo on Linux

* This page contains promotional content

When you use the sudo command on Linux, the PATH you configured as a normal user is not applied and you can end up with “command not found”.
This happens especially often when you try to run a command inside Linuxbrew (Homebrew) with sudo and the command cannot be found.
This article explains how to carry your PATH environment variable over into sudo.

Why PATH changes under sudo

For security reasons, sudo resets environment variables by default.

On many distributions, secure_path is configured in /etc/sudoers, and this fixed PATH is what gets used when running sudo.

# PATH of a normal user
$ echo $PATH
/home/user/.local/bin:/usr/local/bin:/usr/bin:/bin

# PATH under sudo (it has been reset)
$ sudo sh -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Because directories that belong to the user (such as ~/.local/bin) are not included under sudo, commands installed there can no longer be found.

Method 1: Carry the PATH over temporarily

If you want to pass the PATH just once, add an option when you run the command. [1]

Using the –preserve-env option

sudo --preserve-env=PATH your-command

You can name only the specific environment variables you want to carry over.

Using the env command

sudo env PATH="$PATH" your-command

This passes your current PATH straight through when running the command.

Examples

# Run mycli installed in ~/.local/bin as root
sudo --preserve-env=PATH mycli --config /etc/myapp/config.yaml

# or
sudo env PATH="$PATH" mycli --config /etc/myapp/config.yaml

Method 2: Carry the PATH over permanently in sudoers

If adding an option every time is a nuisance, change the sudoers configuration.

Steps

  1. Start visudo (editing the file directly is dangerous, so always use visudo)

    sudo visudo
  2. Comment out the secure_path line

    # Before
    Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    
    # After (add # at the beginning)
    #Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
  3. Add the setting that carries the PATH over

    Defaults    env_keep += "PATH"
  4. Save and exit (:wq in vi)

Checking after the change

$ sudo sh -c 'echo $PATH'
/home/user/.local/bin:/usr/local/bin:/usr/bin:/bin

If the user’s PATH is carried over as it is, it worked.

Method 3: Add to secure_path

There is also a way to keep the existing secure_path while adding only specific directories.

sudo visudo
# Edit it so that the path is appended to the existing one
Defaults    secure_path="/home/linuxbrew/.linuxbrew/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

With this method you can keep the security setting in place while allowing only the paths you need.

Method 4: Run with the full path

This is the approach of specifying the command by absolute path instead of relying on PATH.

# Check where the command is
$ which mycli
/home/user/.local/bin/mycli

# Run it with the full path
$ sudo /home/user/.local/bin/mycli --version

It needs no configuration change and works reliably.

Security considerations

If you disable secure_path or allow PATH through env_keep, there is a risk of a malicious script slipping into the PATH.

MethodBenefitRisk
--preserve-env=PATHUsable only when you need itHas to be specified every time
env_keep += "PATH"Permanently convenientCarries a risk of PATH pollution
Adding to secure_pathLimits which paths are allowedEasy to forget to add one
Specifying the full pathThe safestLonger to type

On a personal development machine env_keep is not a problem, but on a shared server or a production environment adding to secure_path or specifying the full path is recommended.

Summary: an example configuration

Here is a summary of the recommended settings for a personal development environment.

# /etc/sudoers (edit it with visudo)
#Defaults    secure_path="..."   # comment this out
Defaults    env_keep += "PATH"

With this, commands installed in your own space, such as those in ~/.local/bin or Homebrew, can also be run with sudo.

See also