Original URL: http://www.mike.org.cn/articles/linux-linux-bash-command-search-mechanism/
Turn from: Eric cheung:linux (BASH) command search mechanism
This article assumes that the environment is gnu/linux, and that the shell is bash;
Note: In addition, we discuss the premise that when you type a command and do not specify the path of the command, for example, we typed the command is in the form of commandname instead of/path/commandname or./path/commandname. . Once we specify a relative or absolute path to a command (or script or binary), there is no search mechanism.
This article explains: Typically, when we type commands such as LS at the Linux system terminal prompt, how does the shell find this command? What kinds of commands are there in the shell? How are these commands loaded?
First, the classification of Linux commands:
Includes: alias, keyword, function, built-in, $PATH these 5 categories
Second, the Linux command search order:
When we type a command, the shell searches in the order of the Alias->keyword->function,->built-in-> $PATH, on a "first come, first served" basis, This means that if a command named myCMD is present in both alias and function, then the alias's myCMD command will certainly be used (this is not absolute, of course, as the exception is mentioned below).
Third, related
Set +-h, hash, type, command, enable, builtin
1) Hash Command:
First of all, let's look at the hash this command (and what I said above "not absolute" has a relationship!), the hash command is used to record the command path record cache table that the user has typed in the current shell environment, primarily to speed up command search. Let's look at an example:
Example: I type LS, find, pwd, ls, echo "Hello, World" under the shell, mail and if a total of 7 commands (note that LS executes 2 times), the following is the result of history:
1 ls
2 Find
3 pwd
4 ls
5 echo "Hello, World"
6 Mail
7 if
Well, now I execute the hash command, which shows the result:
[[email protected] ~]$ hash
Hits command
1/bin/mail
2/bin/ls
1/usr/bin/find
Do you have any idea what you've found? The left column of the hash table indicates that the command was used several times in the current shell environment, and the right column represents the command path. But we find that the hash cache is missing if,pwd and ECHO3 commands, why? We are here to come to an important conclusion is: (1) hash does not record function, built-in command (in fact, including alias), why? The answer is that they do not have a path, that is, they do not exist under a directory, they are loaded with the shell and then exist in memory, so is it necessary for such a command to be cached to improve search efficiency?!
But some people will say, LS not a hash recorded it? Yes, your observation is very detailed, usually LS in bash is an alias, then, here we first concluded: (2) alias in the definition of the path is included in the alias command will not be recorded in the hash, only the non-specified path alias will be recorded in the hash. Case Examples:
This is the definition of the LS alias in my current shell (bash) environment
[[email protected]//]$ alias ls
Alias ls= ' Ls–color=auto '
(Note: The following "Ls–color=auto" does not specify a path such as/bin/ls)
So, as you can see, I typed the ls command 2 times (the alias of Ls–color=auto), so I could see it recorded in the hash. Here's an example of a write command:
[[email protected]//]$ alias write
-bash:alias:write:not found
[[email protected]//]$ Write
Usage:write user [TTY]
[[email protected]//]$ hash
Hits command
1/usr/bin/write
1/bin/mail
2/bin/ls
1/usr/bin/find
Write this command does not have alias, that is, when executing the Write command is actually found in the path variable/usr/bin/write the binary file to execute, when the hash recorded the write path and was quoted 1 times, I then define the write alias to be the write itself, but specify that the specific path is/usr/bin/write:
[[email protected]//]$ alias write= '/usr/bin/write '
[[email protected]//]$ alias write
Alias write= '/usr/bin/write '
[[email protected]//]$ Write
Usage:write user [TTY]
[[email protected]//]$ hash
Hits command
1/usr/bin/write
1/bin/mail
2/bin/ls
1/usr/bin/find
See, the hits number of write in the hash table is still 1 times; It is important to note that when we define the write alias (Specify the path), path will not be searched, why? Very simple, because the write alias has already indicated its specific path!
Then unalias off write to redefine the write alias:
[[email protected]//]$ Unalias Write
[[email protected]//]$ alias write
-bash:alias:write:not found
[[email protected]//]$ alias write= ' write '
[[email protected]//]$ alias write
Alias Write= ' Write '
[[email protected]//]$ Write
Usage:write user [TTY]
[[email protected]//]$ hash
Hits command
2/usr/bin/write
1/bin/mail
2/bin/ls
1/usr/bin/find
This time, we did not specify a path in the write alias, and when we have defined the write alias to execute write, the hash table will be hits once. It is important to note that when we define the write alias (not specifying the path, compare to the example above), path will be searched, so the hash hits increased. Please remember that if alias is defined as a path-containing aliases command, it will not be recorded in the hash, only alias without the specified path will be recorded in the hash of this conclusion.
In addition, hash because it is built-in command, so use help hash to see the aid. A common hash-r is used to empty the hash table, and hash-d name is used to delete a command. Such as:
[[email protected]//]$ hash
Hits command
3/usr/bin/write
1/bin/mail
2/bin/ls
1/usr/bin/find
Delete the specific:
[[email protected]//]$ hash-d ls
[[email protected]//]$ hash
Hits command
3/usr/bin/write
1/bin/mail
1/usr/bin/find
Empty hash:
[Email protected]//]$ Hash-r
[[email protected]//]$ hash
Hash:hash Table Empty
2) Set +-h:
Set command everyone should be very familiar with, what we are mainly talking about here is the function of Set +-h: Help set can see "H Remember the location of commands as they is looked up." Chinese means memory command. path for easy querying. When we type set +h and then run the hash:
[[Email protected]//]$ set +h
[[email protected]//]$ hash
-bash:hash:hashing disabled
This means "set +h" is used to disable hashing and "set-h" is used to enable hashing.
3) Type:
Use this command to list which class A command belongs to. Such as:
[Email protected]//]$ type-a pwd
PWD is a shell builtin
PWD is/bin/pwd
The pwd belongs to the built-in and path variables.
[[Email protected]//]$ type pwd
PWD is a shell builtin
Directly with type CommandName can tell you which class the command executes at run time.
4) Command:
The purpose of this command is to: if you have a command such as GCC, which is both a function and a command in the path variable, then if you execute GCC directly, in order you execute the command in the function instead of the GCC path variable, GCC skips the function selection.
[[Email protected]//]$ function gcc {echo "Just a test for GCC";}
[Email protected]//]$ gcc
Just a test for GCC
[[Email protected]//]$ command gcc
Gcc:no input Files
5) Enable:
The Enable command, if run directly, lists all built-in commands for the current shell, and enable-n commandname disable the built-in command under the current shell:
[Email protected] ~]$ type-a pwd
PWD is a shell builtin
PWD is/bin/pwd
[Email protected] ~]$ enable-n pwd
[Email protected] ~]$ type-a pwd
PWD is/bin/pwd
[[email protected] ~]$ enable PWD
[Email protected] ~]$ type-a pwd
PWD is a shell builtin
PWD is/bin/pwd
6) Builtin
Used to run a built-in command. For example:
[Email protected] ~]$ Cd/var
[[Email protected] var]$ function pwd {echo "Just a test for pwd";}
[Email protected] var]$ type-a pwd
PWD is a function
PWD ()
{
echo "Just a test for PWD"
}
PWD is a shell builtin
PWD is/bin/pwd
(Note: PWD is both a function and a built-in command, and there is a path variable)
[Email protected] var]$ pwd
Just a test for PWD
[[email protected] var]$ builtin pwd//(Note: At this point we go directly to the PWD this built-in command)
/var
Summary: We all know that the order of the shell in the search command is alias->keyword->function,->built-in-> $PATH, then there are 2 points to note is (1) Hash does not record function, built-in command (in fact, also include Alias), (2) alias if the definition of the path is included in the alias command will not be recorded in the hash, only the alias without the specified path will be recorded in the hash. Also, (3) Do not forget that we are discussing the premise that a is restricted to the specific shell type B) and is only valid in the current shell environment. REMEMBER!!!
Here, let's consider a question:
Take a look at the following implementation:
[[Email protected] var]$ function gcc {echo "Just a test for GCC";}
[[email protected] var]$ alias gcc= ' gcc '
[Email protected] var]$ gcc
Just a test for GCC
[Email protected] var]$/USR/BIN/GCC
Gcc:no input Files
[[email protected] var]$ alias gcc= '/USR/BIN/GCC '
[Email protected] var]$ gcc
Gcc:no input Files
[Email protected] var]$
Why does GCC have a different response when defining GCC's funtion and specifying that the specific/USR/BIN/GCC path is not specified when the two-time alias is defined? According to Alias->keyword->function,->built-in-> $PATH this order, should execute the alias of GCC ah?! Please think!
Of course, don't worry, I'll give you an answer later. But, please think about it!
Four, the command example:
* Alias (alias):
The alias command is usually set in Files ~/.BASHRC and/ETC/BASHRC, ~/.BASHRC is typically used for the user's own environment, and/ETC/BASHRC is used for global definition (i.e., for all users, of course, only for the user shell is bash). The specifics of these two file relationships and how they are loaded are described later.
* Shell keyword (shell keyword):
such as if,while,until,case,for these commands.
* Function (Functions):
Example:
Defines a function called PWD, whose function is to simply display the phrase "my function pwd"
function pwd {echo "my function pwd";}
After you have defined it, you can use set or type-a pwd to view it and cancel it with unset pwd.
* Shell built-in command (shell built-in commands):
command enable to view the built-in commands in all current shell environments; Or use the man CD (any one of the built-in commands) to see the top of the manpage lists all the built-in commands.
* PATH Variable
The variable is defined in file/etc/profile,/etc/profile.d/*.sh (POSIX), ~/.bash_profile (bash).
The order of loading is:/etc/profile First (invoke/etc/profile.d/*.sh), then ~/.bash_profile, then ~/.BASHRC by ~/.bash_profile and then by ~/. BASHRC go to invoke execution ~/.BASHRC, ~/.BASHRC then call execute file/ETC/BASHRC.
1) in order to see the specific loading order, you can add two sentences to the head and tail of the four files, for example:
[email protected] ~]$ cat ~/.BASHRC
echo "Start of ~/.BASHRC"
if [-F/ETC/BASHRC]; Then
. /etc/bashrc
Fi
Alias Ll= ' Ls-l '
Alias cp= ' Cp-i '
Alias mv= ' Mv-i '
Alias rm= ' Rm-i '
......
echo "End of ~/.BASHRC"
Other files, so that when you log into the system with a user, you will see the following display, such as:
Start Of/etc/profile
End Of/etc/profile
Start of ~/.bash_profile
Start of ~/.BASHRC
Start OF/ETC/BASHRC
End OF/ETC/BASHRC
End of ~/.BASHRC
End of ~/.bash_profile
From the above show you can clearly see the loading order of each file and invoke the execution relationship with each other (note view start and end).
2) The relationship between the path variable and the hash
Here, let's look at an example:
[Email protected] ~]$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/ancharn/bin
I first write a script named test.sh in the/home/ancharn/bin directory, which reads as follows:
[Email protected] bin]$ cat/home/ancharn/bin/test.sh
#!/bin/sh
# Just test for PATH and hash
echo "This is my 1st Shell script In/home/ancharn/bin directory."
# End
[Email protected] bin]$
Then, execute the test.sh script as follows:
[Email protected]/]$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/ancharn/bin
[Email protected]/]$ test.sh
This is my 1st Shell script In/home/ancharn/bin directory.
[[email protected]/]$ hash
Hits command
1/home/ancharn/bin/test.sh
Next, create a file with the test.sh name in the/usr/bin directory, with the following contents:
[Email protected]/]$ cat/usr/bin/test.sh
#!/bin/sh
# Just test for PATH and hash
echo "This is my 2nd Shell script In/usr/bin directory."
# End
Continue executing the test.sh script:
[Email protected]/]$ test.sh
This is my 1st Shell script In/home/ancharn/bin directory.
[[email protected]/]$ hash
Hits command
2/home/ancharn/bin/test.sh
What does it mean?
If you follow path in the order of/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/ancharn/bin, you will find/usr/bin and then find/home/ancharn/bin, Note that this premise is that there is no record of the command in the hash table, so we see that the/usr/bin/test.sh script was not executed because the shell went to the hash table to see the cache before executing test.sh, and then proceeded to execute the/home/ancharn/bin /test.sh script, so we see the hits number increased once, and/usr/bin/test.sh will not be executed.
Now, we empty the hash and re-execute the test.sh script:
[Email protected]/]$ Hash-r
[[email protected]/]$ hash
Hash:hash Table Empty
[Email protected]/]$ test.sh
This is my 2nd Shell script In/usr/bin directory.
[[email protected]/]$ hash
Hits command
1/usr/bin/test.sh
It's normal now. So be sure to pay attention to the relationship between path and hash.
Note: Su, su-, Bash–login, bash–norc the difference between these commands is whether the Login-shell is executed, you can su and Su-after, then run the Echo $PATH to see how different.
Well, to answer the above study questions, its core is that alias if defined as alias gcc= ' GCC ', in fact alias->keyword->function,->built-in-> $PATH This order does not change, But to know that alias gcc= ' gcc ' does not specify a path alias will find the "GCC" after the alias, and then to find the later designated ' GCC ', how to find? The next, of course, is keyword->function ... in this order. And if it is alias gcc= '/USR/BIN/GCC ' the definition of the specific path of the alias, then alias execution will directly find the specific file and skip all subsequent searches (that is, keyword->function,-> Built-in-> $PATH). Please keep an eye out for them.
Finally, when you do the experimental verification can be divided into 2 types of verification, because a command cannot belong to both keyword and built-in, so you can:
1) Select a keyword such as while, define a while alias,function, and then write a shell script name for while stored in the path variable at a certain paths;
2) Select a built-in command such as PWD to verify.
"Go" Linux (BASH) command search mechanism