Basic Shell Skills
The shell is the default working environment for a Linux administrator. It is the environment where users and administrators enter commands that are executed by the operating system. Different shells for Linux are available, but Bash is the most common shell. So, when we are talking about “the shell” in this book, we are actually talking about the Bash shell. This chapter provides an overview of some of the items that you will encounter when working with the shell.
Understanding Commands
Working with the shell is all about working with command syntax. Typically, command syntax has three basic parts: the command, its options, and its arguments.
The command is the command itself, such as ls. This command shows a list of files in the current directory. To modify the behavior of the command, you can use options. Options are a part of the program code, and they modify what the command is doing. For instance, when you use the -l (lowercase letter l, not number 1) option with the ls command, a long listing of filenames and properties is displayed.
The word argument is a bit confusing. Generally speaking, it refers to anything that the command addresses, so anything you put after the command is an argument (including the options). Apart from the options that can be used as an argument, commands can have other arguments as well, which serve as a target to the command.
Let’s have a look at an example: the command ls -l /etc. This command has two different arguments: -l and /etc. The first argument is an option, modifying the behavior of the command. The second argument is a target, specifying where the command should do its work. You’ll find these three elements in nearly all commands you work with in a Linux environment.
Executing Commands
The purpose of the Linux shell is to provide an environment in which commands can be executed. The shell takes care of interpreting the command that a user has entered correctly. To do this, the shell makes a distinction between three kinds of commands:
Aliases
Internal commands
External commands
An alias is a command that a user can define as needed. Some aliases are provided by default; type alias on the command line to get an overview. To define an alias, use alias newcommand=‘oldcommand’ (as in the default alias ll=‘ls -l --color=auto’ that has already been created on your system). Aliases are executed before anything else. So, if you have an alias with the name ll but also a command with the name ll, the alias will always take precedence for the command, unless a complete pathname like /usr/bin/ls is used.
An internal command is a command that is a part of the shell itself and, as such, doesn’t have to be loaded from disk separately. An external command is a command that exists as an executable file on the disk of the computer. Because it has to be read from disk the first time it is used, it is a bit slower. When a user executes a command, the shell first looks to determine whether it is an internal command; if it is not, it looks for an executable file with a name that matches the command on disk. To find out whether a command is a Bash internal command or an executable file on disk, you can use the type command. Use for instance type pwd to find out that the pwd command that will be executed is really an alias.
To change how external commands are found by the shell, use the $PATH variable. This variable defines a list of directories that is searched for a matching filename when a user enters a command. To find out which exact command the shell will be using, you can use the which command. For instance, type which ls to find out where the shell will get the ls command from. An even stronger command is type, which will also work on internal commands and aliases.
You should notice that, for security reasons, the current directory is not in the $PATH variable and Linux does not look in the current directory to see whether a specific command is available from that directory. That is why you need to start a command that is in the current directory but nowhere in the $PATH by including ./ in front of it. The dot stands for the current directory, and by running it as ./, you tell Bash to look for the command in the current directory. Although running commands this way is not very common, you will have to do it to run scripts that you’ve created in your current directory.
The $PATH variable can be set for specific users, but in general, most users will be using the same $PATH variable. The only exception to this is the user root, who needs access to specific administration commands. In Exercise 2-1, you learn some of the basics about working with commands.
I/O Redirection
By default, when a command is executed, it shows its results on the screen of the computer you are working on. The computer monitor is used as the standard destination for output, which is also referred to as STDOUT. The shell also has default standard destinations to send error messages to (STDERR) and to accept input (STDIN). Table 2-2 gives an overview of all three.
Table 2-2 Standard Input, Output, and Error Overview
Name |
Default Destination |
Use in Redirection |
File Descriptor Number |
---|---|---|---|
STDIN |
Computer keyboard |
< (same as 0<) |
0 |
STDOUT |
Computer monitor |
> (same as 1>) |
1 |
STDERR |
Computer monitor |
2> |
2 |
So if you run a command, that command would expect input from the keyboard, and it would normally send its output to the monitor of your computer without making a distinction between normal output and errors. Some commands, however, are started in the background and not from a current terminal session, so these commands do not have a monitor or console session to send their output to, and they do not listen to keyboard input to accept their standard input. That is where redirection comes in handy. Redirection is also useful if you want to work with input from an alternative location, such as a file.
Programs started from the command line have no idea what they are reading from or writing to. They just read from what the Linux kernel calls file descriptor 0 if they want to read from standard input, and they write to file descriptor number 1 to display non-error output (also known as “standard output”) and to file descriptor 2 if they have error messages to be output. By default, these file descriptors are connected to the keyboard and the screen. If you use redirection symbols such as <, >, and |, the shell connects the file descriptors to files or other commands. Let’s first look at the redirectors < and >. Later we discuss pipes (the | symbol). Table 2-3 shows the most common redirectors that are used from the Bash shell.
Table 2-3 Common Bash Redirectors
Redirector |
Explanation |
---|---|
> (same as 1>) |
Redirects STDOUT. If redirection is to a file, the current contents of that file are overwritten. |
>> (same as 1>>) |
Redirects STDOUT in append mode. If output is written to a file, the output is appended to that file. |
2> |
Redirects STDERR. |
2>&1 |
Redirects STDERR to the same destination as STDOUT. Notice that this has to be used in combination with normal output redirection, as in ls whuhiu > errout 2>&1. |
< (same as 0<) |
Redirects STDIN. |
In I/O redirection, files can be used to replace the default STDIN, STDOUT, and STDERR. You can also redirect to device files. A device file on Linux is a file that is used to access specific hardware. Your hard disk, for instance, can be referred to as /dev/sda in most cases, the console of your server is known as /dev/console or /dev/tty1, and if you want to discard a command’s output, you can redirect to /dev/null. Note that to access most device files, you need to have root privileges.
Using Pipes
Whereas an I/O redirector is used as an alternative for a keyboard and computer monitor, a pipe can be used to catch the output of one command and use that as input for a second command. If a user runs the command ls, for instance, the output of the command is shown onscreen, because the screen is the default STDOUT. If the user uses ls | less, the commands ls and less are started in parallel. The standard output of the ls command is connected to the standard input of less. Everything that ls writes to the standard output will become available for reading from standard input in less. The result is that the output of ls is shown in the less pager, where the user can browse up and down through the results easily.
As a Linux administrator, you will use pipes a lot. Using pipes makes Linux a flexible operating system; by combining multiple commands using pipes, you can create “super” commands that make almost anything possible. In Exercise 2-2, you use I/O redirectors and pipes.
History
A convenient feature of the Bash shell is the Bash history. Bash is configured by default to keep the last 1,000 commands a user used. When a shell session is closed, the history of that session is updated to the history file. The name of this file is .bash_history and it is created in the home directory of the user who started a specific shell session. Notice that the history file is written to only when the shell session is closed; until that moment, all commands in the history are kept in memory.
The history feature makes it easy to repeat complex commands. There are several ways of working with history:
Type history to show a list of all commands in the Bash history.
Press Ctrl-r to open the prompt from which you can do backward searches in commands that you have previously used. Just type a string and Bash will look backward in the command history for any command containing that string as the command name or one of its arguments. Press Ctrl-r again to repeat the last backward search.
Type !number to execute a command with a specific number from history.
Use history -d number to delete a specific command from history. Notice that this command will renumber all other lines in history: if you’ve removed line 31, the line previously numbered as line 32 will now be line 31.
Type !sometext to execute the last command that starts with sometext. Notice that this is a potentially dangerous command because the command that was found is executed immediately!
In some cases it might be necessary to wipe the Bash history. This capability is useful, for instance, if you’ve typed a password in clear text by accident. If that happens, you can type history -c to clear the current history. Commands from this session won’t be written to the history file when you exit the current session. If you want to remove both the current history and the contents of the .bash_history file, then type history -w immediately after running the history -c command. Alternatively, use history -d number to remove a specific command from history.
Exercise 2-3 guides you through some history features.
Bash Completion
Another useful feature of the Bash shell is command-line completion. This feature helps you to find the command that you need, and it also works on variables and filenames.
Bash completion is useful when you’re working with commands. Just type the beginning of a command and press the Tab key. If there is only one option for completion, Bash will complete the command automatically for you. If there are several options, you need to press Tab once more to get an overview of all the available options. In Exercise 2-4, you learn how to work with these great features.