Bash如何执行命令?脚本与终端命令执行原理探究
Great question! Your initial idea of using a giant chain of if statements to match every possible command makes sense on a small scale, but as you noticed, it's totally impractical for a real shell like Bash. Let's break down how Bash actually handles commands, and confirm your later hypothesis.
First: Bash Doesn't Use if Chains for Most Commands
Your first approach would mean maintaining an endless list of command checks—and it would break as soon as someone installs a new program, writes a custom script, or even uses a command from a different directory. Bash doesn't work this way at all.
Your Hypothesis Is Mostly Correct (With Key Nuances)
You're right that Bash locates executable files and runs them—though it uses a more structured process than just calling which. Here's the step-by-step breakdown:
1. Check for Built-in Commands First
Some common commands like pwd, echo, cd, and export are Bash built-ins. That means the code to execute them is part of the Bash program itself. When you run pwd, Bash doesn't need to find an external file—it just runs the built-in function directly in its own process.
You can check if a command is a built-in with:
type pwd # Output: pwd is a shell builtin
2. Look for External Executables in $PATH
For commands that aren't built-ins (like firefox, gedit, or /bin/pwd), Bash uses the $PATH environment variable. This variable is a colon-separated list of directories where system and user-installed executables live:
echo $PATH # Example output: /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Bash searches each directory in $PATH in order, looking for a file with the same name as your command that has executable permissions. The first matching file it finds is the one it runs.
If you specify a full or relative path (like ./my_script.sh or /usr/bin/firefox), Bash skips the $PATH search and goes straight to that file.
3. How Bash Runs the Executable
Once Bash finds the right executable file, it uses two core system calls:
fork(): Creates a copy of the Bash process (a child process).exec(): Replaces the child process with the executable file you want to run. The kernel handles loading the file's code and data into memory and starting execution.
Bash doesn't need to know "how to call" the program—it just needs to confirm the file is executable and in a valid format (like ELF on Linux). The kernel takes care of the rest.
Bonus: Other Command Types Bash Handles
Before even checking built-ins or $PATH, Bash looks for:
- Aliases: Custom shortcuts you've defined (e.g.,
alias ll='ls -l'). - Shell Functions: Custom code blocks you've written (e.g.,
myfunc() { echo "Hello"; }).
These take priority over both built-ins and external commands unless you explicitly force the external version (e.g., command ls to bypass an alias).
To Sum Up
Your core idea was right: Bash doesn't hardcode checks for every possible command. For external programs, it locates the executable file and asks the kernel to run it. The key distinction is built-in commands, which are part of Bash itself for efficiency and tight integration with shell functionality.
内容的提问来源于stack exchange,提问作者codedcosmos

