Running a program in the command line activates a whole process to find and execute that program. It's very important to understand how it works, since problems with launching newly installed programs can occur regularly with all developers.
A program, no matter what it does, is just a file or set of files on disk. One of these files must be executable. Do you remember the x
from the lesson about access rights? Well, you can only execute a program if it is executable, otherwise trying to run it will result in an error.
The whole system for running programs on *nix systems is based on conventions. When a command is entered in the command line, such as ls
, the shell starts searching for an executable named ls
in the list of directories given in the PATH
environment variable.
echo $PATH
/home/hex/.local/bin:/home/hex/bin/:/home/hex/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Directories are separated from each other by a colon. This list includes both system-wide paths and paths specific to a particular user. In your case, PATH
will be different. The program search process is as follows. Shell goes through the directories from left to right and looks for one that has an executable ls
file. If there is no such file, an error will be displayed:
wrongname
bash: wrongname: command not found
I must emphasize that order is important. If a file with the same name is in several directories at the same time, the one in the directory furthest to the left will be the one that is found.
If you want to know where the executable file of a particular program is, you can use the command type
(and also which
and whereis
):
type cp
cp is /bin/cp
whereis cp
cp: /bin/cp
which cp
/bin/cp
ls -al /bin | grep cp
-rwxr-xr-x 1 root root 141528 Jan 18 2018 cp
You can see from the output above that cp
belongs to the superuser, but anyone can execute it.
Note that almost all directories that hold executable program files end in bin
. It's general convention that we say "binary" (technically it's not always binary, but it doesn't matter). Package managers are aware of these directories and move their binaries to one of the directories included in PATH
when installing programs. For newly installed programs, this is usually /usr/local/bin
. Sometimes you need to extend PATH
, especially when installing through programming languages' package managers, but do it carefully, and only do it if you can't do it any other way.
In some situations, the program you want to run is not in the search paths (that are written in PATH
) and should not be there. If its executable is located directly in the current directory, it is logical to assume that if you type the file name and run it, the program will run. However, this is not the case.
This is done for safety reasons. After all, maybe you wanted to run a standard program, but a malicious person put a program with the same name in the current directory, but the one they put in does something bad. For this reason, a direct program launch should always be a path to a file, such as path/to/executable/file
. What if the file is in the current directory? This is where the ./
reference helps us:
pwd
/home/hex
cd test/
ls -al
total 16
drwxr-xr-x 2 hex hex 4096 Sep 10 15:24 .
drwxr-xr-x 1 hex hex 4096 Sep 10 15:24 ..
-rwxr-xr-x 1 hex hex 60 Sep 10 15:24 executable
executable
bash: executable: command not found
./executable
Hello from executable!
- From the home directory, go to the
test
directory. - It contains an executable file called
executable
which, when run, displays the messageHello from executable!
- Attempting to run by the name
executable
ends in an error - Starting the command with ./ will be successful
Changing the PATH variable
In general, doing it yourself isn't recommended. When installed correctly, most programs add their own executable files to the locations they need. In some cases, they show hints on how to do it straight after installation.
To manually change the PATH variable, you need to edit one of the Bash configuration files. These files are in the user's home directory:
- .bashrc
- .bash_profile
- .profile
Depending on the terminal settings, Bash will load one set of files, or another set. If you have a .bashrc file in your home directory, then try it, if not, then use the other files in the order they are listed above. Add the following line to this file:
export PATH=$PATH:/path/to/directory
Where /path/to/directory is the path to the directory with the executable files.
After making the changes, don't forget to restart the terminal.
Do it yourself
- Try to find out where the
tree
program installed in one of the previous lessons is in your system.