A Fundamental Overview of GNU/Linux - Shells: A Basic Overview
What is a “shell”?
Per the ``:
Shells interface users with the kernel by enabling them to submit their requests for processing.
[...]
The shell is referred to as the command interpreter, and it is an interface between a user and the kernel. The shell accepts instructions, interprets them, and passes them to the kernel for processing. The kernel uses all hardware and software components required for successfully processing the instructions. When finished, it returns the results to the shell and displays them on the screen. The shell also shows appropriate error messages, if generated.
They are named “shells” because they are considered the outer “layer” between the kernel and the
Shells come in many different flavors, with the default shell on most Linux systems being the “Bourne Again Shell”, also known as bash
. bash is based off the Bourne shell (also known as sh
), with many of the conventions from sh
being used in bash
. Other flavors of shells include zsh
, ksh
, and tcsh
.
Let’s take a look at a simple command prompt in bash
:
evan@US-1N5LN13:~$
By default, the command prompt brings up a user as well as the hostname of the machine. The prompt also identifies who is using the machine, with the “$” or “%” symbol identifying a non-root user, and the “#” symbol being used to identify the root user (we will go into this concept at a later time).
Keep in mind that this prompt can be customized and changed based on the preference of the user. Any commands entered by the user will be shown at the end of the prompt, similar to the following:
evan@US-1N5LN13:~$ ls -lah
Going into some features of the bash
shell:
Variable Storage and Substitution:
According to the ``, a variable is:
[...] a temporary storage of data in memory. It stores information that is used for customizing the shell environment and by many ssytem and application processesto function properly.
As to what data can be stored in these variables, lets take a look at our own, when we type in the env
command:
HOSTTYPE=x86_64
LANG=en_US.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/mnt/c/Program Files (x86)/Common Files/Oracle/Java/javapath:/mnt/c/WINDOWS/system32:/mnt/c/WINDOWS:/mnt/c/WINDOWS/System32/Wbem:/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/:/mnt/c/WINDOWS/System32/OpenSSH/:/mnt/c/Program Files/Dell/Dell Data Protection/Encryption/:/mnt/c/Users/evan.fleming/AppData/Local/Programs/Python/Python310/Scripts/:/mnt/c/Users/evan.fleming/AppData/Local/Programs/Python/Python310/:/mnt/c/Users/evan.fleming/AppData/Local/Programs/Python/Launcher/:/mnt/c/Users/evan.fleming/AppData/Local/Microsoft/WindowsApps:/mnt/c/Users/evan.fleming/AppData/Local/Google/Cloud SDK/google-cloud-sdk/bin:/mnt/c/Users/evan.fleming/AppData/Local/Programs/Microsoft VS Code/bin
TERM=xterm-256color
WSLENV=
NAME=US-1N5LN13
HOME=/home/evan
USER=evan
LOGNAME=evan
SHELL=/bin/zsh
WSL_DISTRO_NAME=Ubuntu-16.04
SHLVL=1
PWD=/mnt/c/Users/evan.fleming
OLDPWD=/mnt/c/Users/evan.fleming
ZSH=/home/evan/.oh-my-zsh
PAGER=less
LESS=-R
LSCOLORS=Gxfxcxdxbxegedabagacad
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
VIRTUAL_ENV_DISABLE_PROMPT=1
_=/usr/bin/env
As can be seen above, variables can store alphanumeric characters, whitespace, and some special characters. This is useful when needing to perform command or variable substitution, as we will see later on.
There are two types of variables that can be stored: local, and environment variables. What we see above are our environment variables, likely set during our configuration of the various services that we are currently using in our session.
Local variables are private to the shell in which it is created and its value cannot be used by processes that are not started in that shell. This leads into the concept of current shell and child shell (or sub-shell); effectively, a shell can be created inside of the initial shell that can run its own commands and contain its own variables.
$ echo "$(cat /etc/*release | grep 'UBUNTU_') is great!"
UBUNTU_CODENAME=xenial is great!
In the above example, the child shell (the start of which is signified by the “$” symbol, think of it as a temporary variable) is using the cat
command to display text from any file with the name “release” in its title, and looking for the specified string. It then passes the result of this, once it has finished, back to the inital shell, containing the echo command.
If, say, there was a long-running process that child shell is completing, the initial shell (or parent shell) sleeps until the child shell returns with its own result.
Keep in mind that both the initial and child shells can reference environment variables, but each contains local variables during the course of its runtime.
Some times over the course
To understand shells, I believe it’s helpful and important to have a good basis on kernel processes. So… what do we define as a kernel process?
From the ``:
A process is a unit for provisioning system resources. It is any program, application, or command that runs on the system. A process is created in memory in its own address space when a program application, or command, is initiated. Process are organized in a hierarchichal fashion. Each process has a *parent process* (a.k.a a *calling process*) that spawns it. A single parent process may have one or many child processes and passes many of its attributes to them at the time of their creation. Each process is assigned a unique identification number, known as the *process identifier* (PID), which is used by the kernel to manage and controll the process through its lifecycle. When a process completes its lifecycle or is terminated, this event is rpeported back to its pareent process, and all the resources provisioned to it are then freed and the PID is removed.
Let’s take a look at what this looks like. I’m going to open a random text document in vim, and take a look at the process from outside.
If I type in ps
:
PID TTY TIME CMD
74 pts/1 00:00:00 bash
92 pts/1 00:00:00 ps
I’m given some basic information about two running processes: bash
, and ps
.
Basic information about each process is divided into 4 these columns, PID
, TTY
, TIME
, and CMD
.
Notice how my vim process isn’t showing up here. Why? Well, the ps
command, without any flags or or arguments, only lists processes specific to the terminal where the command is run. If we want more information regarding processes