• Earn real money by being active: Hello Guest, earn real money by simply being active on the forum — post quality content, get reactions, and help the community. Once you reach the minimum credit amount, you’ll be able to withdraw your balance directly. Learn how it works.

Linux Shells: from classics to innovations

dEEpEst

☣☣ In The Depths ☣☣
Staff member
Administrator
Super Moderator
Hacker
Specter
Crawler
Shadow
Joined
Mar 29, 2018
Messages
13,861
Solutions
4
Reputation
32
Reaction score
45,552
Points
1,813
Credits
55,350
‎7 Years of Service‎
 
56%
Shells: from classics to innovations

Surely many people know the sh and bash shells. Most of us have also heard something about zsh and fish. However, the list does not end there.

Nowadays, there are many shells, but not all of them are used. Today we will consider the most basic examples and look at their key features.

The sh shell (Bourne shell)

This shell was written by Steve Bourne in 1977 and is the oldest of those known to the public.

The Bourne shell was the first full-fledged shell and contained the functionality that is now implemented by all current followers: using variables, executing commands and functions, and redirecting input and output.

Now sh is a link to the sh-compatible shell for a number of reasons:

Bash:
$ ls -l | grep sh
sh -> dash

In modern systems, the Bourne shell is no longer used as a user shell, but is useful as a command interpreter.

That's why it exists as a link, so as not to break compatibility for script execution. Do you still remember about shebang?)

Bash:
#!/bin/sh

Bash shell (Bourne again shell)

It was developed within the GNU project as an improved implementation of the Bourne shell in 1989.

The main creators of bash are Brian Fox and Chet Ramey. The name can be translated as "Bourne shell reborn". Most likely, the most popular shell today.

This shell is the successor of sh and significantly expands its functionality. However, it is still ancient and not as beautiful and configurable as the newer zsh and fish.

Zsh shell (Z shell)

A free modern sh-compatible shell, created in 1990. It has a number of advantages over bash, mainly concerning work in interactive mode.

Bash:
$ sudo apt install zsh

Zsh supports autocompletion, typo correction, syntax highlighting, and quite a powerful configuration of appearance and functionality through themes and plugins.

However, zsh is fully revealed only through configuring configs. When you first run it, you will probably ask yourself: Why do you need it at all - the same bash... Yes, you need to manually configure it.

A highly recommended addition to the zsh shell is the "OH MY ZSH (
This link is hidden for visitors. Please Log in or register now.
)" framework, which is designed to manage zsh settings and expand its functionality through plugins and themes.

Fish shell (friendly interactive shell)

Fish is not such a "bearded" shell. The first version dates back to 2005. Against the background of its main colleagues in the shop, which were released in the last century, fish (
This link is hidden for visitors. Please Log in or register now.
) is a fresh cucumber.

Bash:
$ sudo apt-add-repository ppa:fish-shell/release-3
$ sudo apt update
$ sudo apt install fish

If you need more functionality than bash, but you don't want to dig into configs like with zsh, you can consider this shell.

Everything would be fine, but there is a nuance: fish is a POSIX-incompatible shell. This means that the rules dictated by the POSIX standard for a number of shells (bash, zsh, etc.) have no effect on fish.

Example. This is how we define local variables in bash and zsh:

Bash:
$ MY_VAR="Hello"

Let's try to repeat the same in fish:

Bash:
$ MY_VAR="Hello"
fish: Unsupported use of '='. In fish, please use 'set MY_VAR "Hello"'

This won't work here. In fish, variables are defined as follows:

Bash:
$ set MY_VAR "Hello"

Get the idea yet? If you write a script in fish-specific syntax and try to run it through a bash, sh or zsh interpreter, it will probably crash with an error.
 

Understanding shell types: interactive, non-interactive, login, non-login​


Yes, there is another trick with shells. Many people are confused by the process of setting up shells precisely because they are not aware of the typical differences. Today I will try to give you a basic understanding of each of the types, so that it will be easier to understand the configs later.

"Interactive" shells

To simplify as much as possible, an interactive shell is one that we work with through manual input - we type a command, pass it to the shell as input and see the result upon completion. When you launch a terminal, the shell starts in interactive mode.

"Non-interactive" shells

This is the shell startup mode when it does not interact directly with the user. They are usually launched to execute commands or scripts and terminate when the task is completed. Everyone remembers that shebang:

Bash:
#!/bin/sh

So, to run a script, we first open bash (interactive shell) and specify the path:

Bash:
$ ./script.sh

Then bash will launch the sh interpreter (non-interactive shell), after which it will "quietly" execute the script.

This is IMPORTANT to remember! Scripts run in non-interactive shells and your settings in the "~/.bashrc" file will be useless. Why don't such shells load configs? Good question. There are several reasons:

1) the script should not rely on user settings - be "user-dependent". If the user "planed" the script, relying, for example, on his aliases, portability will be violated and it will probably not start for another person.

2) reading and processing configs can take time. Without additional preparations, the script will simply work faster.

"Login" shells

This shell is created by the first user process when it successfully logs into the system and opens a session via tty or ssh. If you logged in via the GUI - display manager, the "login shell" is usually replaced by a window manager or session manager.

This type of shell is not created all the time, as we open the terminal and is distinguished by the fact that it reads additional configs. It can be clearly identified by the '-' prefix for the executable file. Let's log in as a user via tty and check:

Bash:
$ ps -auxf
(root) /bin/login -p --
(user) \_ -bash
\_ ps -auxf

Now let's launch another shell inside the parent one and make sure that the "login shell" status is not always issued:

Bash:
$ bash
$ ps -auxf
/bin/login -p --
\_ -bash
\_ bash
\_ ps -auxf

You can also find out the shell type using the '0' variable:

Bash:
$ echo $0
-bash

"Non-login" shells

Created during normal startup - without user authorization. All you need to initialize such a shell is to simply open a terminal or launch the executable file yourself without additional flags that put the shell into "login" mode: "-l" and "--login".
 

Shell configuration​


So, we continue to stomp further and delve into the structure of shells. Today we will consider what configuration files and in what order the shell executes in order to set up its environment.

We will talk about configs in the context of the bash shell, but there are not many differences between their variations.

Stages of the "login shell" configuration

So, we have successfully logged in and opened a session via tty or ssh... What files were used by our "ancestral ☝️" shell "-bash" and in what order?

1) the shell executes the system script "/etc/profile"
2) the script "/etc/profile" executes each file "*.sh" (readable), which is located in the directory "/etc/profile.d/":

Bash:
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi

3) then ONLY one of the following user files is executed (in this exact order): ~/.bash_profile, ~/.bash_login, ~/.profile. As a rule, each of these scripts should eventually call ~/.bashrc:

Bash:
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi

4) when that's it, the shell exits, and if possible, runs the "~/.bash_logout" script.

Stages of "non-login shell" configuration

Here, everything is usually simpler: when the interactive shell is launched in normal mode (non-login), only the user script ~/.bashrc is executed. It is executed every time the shell starts, which implies that it contains "reusable" commands.

Also, in some distros, the bash shell binary can be compiled with the "-DSYS_BASHRC" flag, which leads to the execution of the system script "/etc/bash.bashrc" before the user's "~/.bashrc".

Wait, but "/etc/profile" is not called? No, the purpose of "profile" files is to execute commands only for "login" shells. Their execution is usually required once per session.
 
Back
Top