1. Overview
In this tutorial, we’ll go over the causes for the “command not found” error when using sudo and explore possible fixes.
2. Linux $PATH Variable
The Linux $PATH variable specifies a colon-separated list of directories to be searched when executing a command.
For example, the default value of this variable is usually /usr/bin:/usr/local/bin, which tells the shell to search /usr/bin and /usr/local/bin when we execute a command. This allows us to just use ls instead of /usr/bin/ls to execute ls.
If we remove /usr/bin from $PATH, ls won’t be found:
$ echo $PATH
/usr/bin:/usr/local/bin
$ ls
Downloads Files Music ...
$ PATH=/usr/local/bin
$ ls
/bin/sh: ls: not found
We can add additional directories by setting PATH=”$PATH:/path/to/my/directory:/path/to/another/directory”.
Let’s say we have a script called myscript in the $HOME/bin directory, and we want to execute it without typing the full path each time.
We just add $HOME/bin to $PATH:
$ myscript
/bin/sh: myscript: not found
$ PATH="$PATH:$HOME/bin"
$ myscript
My Script!
$ which myscript
/home/baeldung/bin/myscript
3. “Permission Denied” When Running Script
We can sometimes get a “permission denied” error when trying to run scripts. This happens if the scripts don’t have an executable bit set and are treated as text files instead.
We can run chmod with the +x flag to mark files as executable:
$ echo "echo Hello" > myscript
$ ./myscript
/bin/sh: ./myscript: Permission denied
$ chmod +x ./myscript
$ ./myscript
Hello
4. Fixing the “Command Not Found” Error
The “command not found” error can occur if we have set a custom $PATH to run our scripts. This is because sudo might execute commands with a fresh environment instead of inheriting modified environment variables.
4.1. Fixing the Error for a Single Command
We can pass the -E flag to sudo to make it preserve the current environment variables:
$ echo $PATH
/usr/bin:/home/baeldung/bin
$ myscript
My Script Run As baeldung
$ sudo myscript
sudo: myscript: command not found
$ sudo -E myscript
My Script Run As root
Here myscript is located in /home/baeldung/bin.
4.2. Fixing the Error Permanently
To fix this error permanently, we can either configure sudo to always inherit the $PATH variable or set a $PATH for it manually by modifying /etc/sudoers.
First, we need to run visudo to open up the /etc/sudoers file for modification.
Now we can use the env_keep option to make sudo inherit $PATH:
Defaults env_keep += "PATH"
We can also hard-code $PATH with the secure_path option where /path/to/my/directory is the directory we want to append:
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/path/to/my/directory"
We should note that the value of secure_path is hard-coded and won’t dynamically update if we modify the $PATH variable. Therefore, /etc/sudoers must be modified manually.
5. Conclusion
In this article, we discussed the Linux $PATH variable and explored how sudo interacts with it.
We also learned about configuring sudo to fix common issues with $PATH.