Command load and execution in Bash

The booting post explains the process from power-on the computer till a bash prompt is presented to the user.

At this point the user can enter commands to perform any desired action.

Command launch process

Once you get access to a terminal (does not matter whether it is via Alt-F(n) terminal or an Xterminal), bash is already showing the defined prompt and waiting for a command to by typed. It is waiting for your typing at standard input (stdin).

When hitting “Enter” after the command, bash performs these actions:

The search in the PATH environment variable is done sequentially, following the order of the directories from left to right. When the command is found in a directory, bash stops the search. The command name, with its full path, is then informed in the cache. This internal cache is a hash table. Looking for the commands in the hash is much faster than having to scan each time the directories informed in PATH.

You can easily check the hash table content typing the built-in command hash (do this after having run a couple of commands).

Behind the curtains

Several interesting things are happening “behind the curtains”.

Let’s continue supposing that the command is an external bash command. As commented, regardless whether the command is in the cache o not, bash has to load into memory the binary file of the command in order to execute it. This leads to several actions:

All this is happening while the computer does many other things (for instance playing a mp3 file or responding to the keyboard). This is possible because there are several mechanisms to share the CPU time among running processes. This is done by the scheduler, a very important component of the kernel. Be aware of how fast a CPU is and how many things it can do looking at the Multitasking explanation in the fork and exec section or at ‘speed of components’ explanations in the “Some numbers and magnitudes” section.

Interrupts are also a very important mechanism to get CPU time. This mechanism is used by the electronic that control the keyboard when a key is pressed so it can be shown in the screen “immediately” (from a user time point of view…)

There are also several mechanisms to exchange information among processes (so the parent and the child can communicate to each other). Find in signals) information about signaling among processes (for instance when the parent is ordered to die)

Waiting for the child

As we are in an interactive session, and the command is launched in the foreground (see bash job control, bash will wait (and therefore not presenting the prompt) till the termination of the command that has been run in the separated sub-shell. It will collect it exit status (also known as return code) of the child in the “$?” shell variable.

Another command??

When the prompt is back, bash is ready to accept new commands. These commands will go thorough the described process.

From here, there are many options that bash and the whole system offer to us. Commands can be written (scripted) in files that will be interpreted by bash. As bash contains its own programming language, these scripts can control things and behave accordingly via flow control instructions like ‘if’, ‘for’ and many more.

You can find many good resources in the Net about programming in bash, but you can also check the things Mico Maco finds helpful for him at the Bash Programming section.

There are also some bash tip at Bash cmd line tips

Bash code review

At the time of writing this post, Mico Maco downloaded the bash version in use (bash v4.4) to have a look at its code. Mico Maco highly recommends doing this, so you can download the bash code at the GNU site.

If you are looking at version 4.4, look around line 5095 of program “execute_cmd.c” to see the code that will run a command from disk in a subshell (what has been explained in this page…). It does many things, as bash is a very powerful shell. Keep reading lines till line 5251 (I recommend just reading the comments to get what is going on). There is a call to a function named “shell_execve()“. I leave it you to imagine what this function does, but if you look at like 5445 in the same file, you will find it. There is where, among many other things needed by bash, the command is executed (bash has already done the fork…).