Previous Page
Next Page

5.1. Objective 1: Work on the Command Line

Every computer system requires a human interface component. For Linux system administration, a text interface is typically used. The system presents the administrator with a prompt, which at its simplest is a single character such as $ or #. The prompt signifies that the system is ready to accept typed commands, which usually occupy one or more lines of text. This interface is generically called the command line.

It is the job of a program called a shell to provide the command prompt and to interpret commands. The shell provides an interface layer between the Linux kernel and the human user, which is how it gets its name. The original shell for Unix systems was written by Steve Bourne and was called simply sh. The default Linux shell is bash, the Bourne-Again Shell, which is a GNU variant of sh. The bash shell is the subject of an entire LPI Topic, covered in Chapter 17. At this point, we are primarily concerned with our interaction with bash and the effective use of commands.

5.1.1. The Interactive Shell

The shell is a powerful programming environment, capable of automating nearly anything you can imagine on your Linux system. The shell is also your interactive interface to your system. When you first start a shell, it does some automated housekeeping to get ready for your use, and then presents a command prompt. The command prompt tells you that the shell is ready to accept commands from its standard input device, which is usually the keyboard. Shells can run standalone, as on a physical terminal, or within a window in a GUI environment. Whichever the case, their use is the same.

5.1.1.1. Shell variable basics

During execution, bash maintains a set of shell variables that contain information important to the execution of bash. Most of these variables are set when bash starts, but they can be set manually at any time.

The first shell variable of interest in this Topic is called PS1 (which simply stands for Prompt String 1). This special variable holds the contents of the command prompt that are displayed when bash is ready to accept commands (there is also a PS2 variable, used when bash needs multiple-line input to complete a command). You can easily display the contents of PS1, or any other shell variable, by using the echo command with the variable name preceded by the $ symbol:

$ echo $PS1
\$

The \$ output tells us that PS1 contains the two characters \ and $. The backslash character tells the shell not to interpret the dollar symbol in any special way (that is, as a metacharacter, described later in this section). A simple dollar sign was the default prompt for sh, but bash offers options to make the prompt much more informative. On your system, the default prompt stored in PS1 is probably something like:

[\u@\h \W]\$

Each of the characters preceded by backslashes have a special meaning to bash, while those without backslashes are interpreted literally. In this example, \u is replaced by the username, \h is replaced by the system's hostname, \W is replaced by the unqualified path (or basename) of the current working directory, and \$ is replaced by a $ character. (Unless you are root, in which case \$ is replaced by #.) This yields a prompt of the form:

[jdean@linuxpc jdean]$

How your prompt is formulated is really just a convenience and does not affect how the shell interprets your commands. However, adding information to the prompt, particularly regarding system, user, and directory location, can make life easier when hopping from system to system and logging in as multiple users (as yourself and root, for example). See the online documentation on bash for more information on customizing prompts.

Another shell variable that is extremely important during interactive use is PATH , which contains a list of all the directories that hold commands or other programs you are likely to execute. A default path is set up for you when bash starts. You may wish to modify the default to add other directories that hold programs you need to run.


Tip: Every file in the Linux filesystem can be specified in terms of its location. The less program, for example, is located in the directory /usr/bin. Placing /usr/bin in your PATH enables you to execute less by simply typing less rather than the explicit /usr/bin/less.Also be aware that . (the current directory) is not included in the PATH either implicitly (as it is in DOS) or explicitly for security reasons. To execute a program named foo in the current directory, simply run ./foo.

For bash to find and execute the command you enter at the prompt, the command must be one of the following:

  • A bash built-in command that is part of bash itself

  • An executable program located in a directory listed in the PATH variable

  • Explicitly defined

The shell holds PATH and other variables for its own use. However, many of the shell's variables are needed during the execution of programs launched from the shell (including other shells). For these variables to be available, they must be exported, at which time they become environment variables. Environment variables are passed on to programs and other shells, and together they are said to form the environment in which the programs execute. PATH is always made into an environment variable. Exporting a shell variable to turn it into an environment variable is done using the export command:

$ export MYVAR

When a variable is exported to the environment, it is passed into the environment of all child processes. That is, it will be available to all programs run by your shell.

5.1.1.2. Entering commands at the command prompt

Commands issued to the shell on a Linux system generally consist of four components:

  • A valid command (a shell built-in, program, or script found among directories listed in the PATH, or an explicitly defined program)

  • Command options, usually preceded by a dash

  • Arguments

  • Line acceptance (i.e., pressing the Enter key), which we assume in the examples

Each command has its own unique syntax, although most follow a fairly standard form. At minimum, a command is necessary:

$ ls

This simple command lists files in the current working directory. It requires neither options nor arguments. Generally, options are letters or words preceded by a single or double dash and are added after the command and separated from it by a space:

$ ls -l

The -l option modifies the behavior of ls by listing files in a longer, more detailed format. In most cases, single-dash options can be either combined or specified separately. To illustrate this, consider these two equivalent commands:

$ ls -l -a
$ ls -la

By adding the -a option, ls displays files beginning with a dot (which it hides by default). Adding that option by specifying -la yields the same result. Some commands offer alternative forms for the same option. In the preceding example, the -a option can be replaced with --all:

$ ls -l --all

These double-dash full-word options are frequently found in programs from the GNU project. They cannot be combined like the single-dash options can. Both types of options can be freely intermixed. Although the longer GNU-style options require more typing, they are easier to remember and easier to read in scripts than the single-letter options.

Adding an argument further refines the command's behavior:

$ ls -l *.c

Now the command will give a detailed listing only of C program source files, if any exist in the current working directory.


Tip: Using the asterisk in *.c allows any file to match as long as it ends with a .c extension. More information on file globbing and using wildcards will be discussed later in this chapter.

Sometimes, options and arguments can be mixed in any order:

$ ls --all *.c -l

In this case, ls was able to determine that -l is an option and not another file descriptor.

Some commands, such as tar and ps, don't require the dash preceding an option because at least one option is expected or required. To be specific, ps doesn't require a dash when it is working like BSD ps. Since the Linux version of ps is designed to be as compatible as possible with various other versions of ps, it sometimes does need a dash to distinguish between conflicting options. (As an example, try ps -e and ps e.)

Also, an option often instructs the command that the subsequent item on the command line is a specific argument. For example:

$ tar cf mytarfile file1 file2 file3
$ tar -cf mytarfile file1 file2 file3

These equivalent commands use tar to create an archive file named mytarfile and put three files (file1, file2, and file3) into it. In this case, the f option tells tar that archive filename mytarfile follows immediately after the option.

Just as any natural language contains exceptions and variations, so does the syntax used for GNU and Unix commands. You should have no trouble learning the essential syntax for the commands you need to use often. The capabilities of the command set offered on Linux are extensive, making it highly unlikely that you'll memorize all of the command syntax you need. Most systems administrators are constantly learning about features they've never used in commands they use regularly. It is standard practice to regularly refer to manpages or infopages and other documentation on commands you're using, so feel free to explore and learn as you go.

5.1.1.3. Entering commands not in the PATH

Occasionally, you will need to execute a command that is not in your path and not built into your shell. If this need arises often, it may be best to simply add the directory that contains the command to your path. However, there's nothing wrong with explicitly specifying a command's location and name completely. For example, the ls command is located in /bin. This directory is most certainly in your PATH variable (if not, it should be!), which allows you to enter the ls command by itself on the command line:

$ ls

The shell will look for an executable file named ls in each successive directory listed in your PATH variable and will execute the first one it finds. Specifying the fully qualified filename for the command eliminates the directory search and yields identical results:

$ /bin/ls

Any executable file on your system may be started in this way. However, it is important to remember that some programs may have requirements during execution about what is listed in your PATH. A program can be launched normally but may fail if it is unable to find a required resource due to an incomplete PATH.

5.1.1.4. Entering multiple-line commands interactively

In addition to its interactive capabilities, the shell also has a complete programming language of its own. Many programming features can be very handy at the interactive command line as well. Looping constructs, including for, until, and while are often used this way. (Shell syntax is covered in more detail in Chapter 17.) When you begin a command such as these, which normally spans multiple lines, bash prompts you for the subsequent lines until a valid command has been completed. The prompt you receive in this case is stored in shell variable PS2, which by default is >. For example, if you wanted to repetitively execute a series of commands each time with a different argument from a known series, you could enter the following:

$ ...series of commands on arg1...
command output
$ ...series of commands on arg2...
command output
$ ...series of commands on arg2...
command output

Rather than entering each command manually, you can interactively use bash's for loop construct to do the work for you. Note that indented style, such as what you might use in traditional programming, isn't necessary when working interactively with the shell:

$ for var in arg1 arg2 arg3 
> do 
> echo $var 
> ...series of commands... 
> done 
arg1
command output 
arg2
command output 
arg3
command output 

5.1.1.5. Entering command sequences

There may be times when it is convenient to place multiple commands on a single line. Normally, bash assumes you have reached the end of a command (or the end of the first line of a multiple-line command) when you press Return. To add more than one command to a single line, separate the commands and enter them sequentially with the command separator, a semicolon. Using this syntax, the following commands:

$ ls
$ ps

are, in essence, identical to and will yield the same result as the following single-line command that employs the command separator:

$ ls ; ps

On the Exam

Command syntax and the use of the command line is very important. Pay special attention to the use of options and arguments and how they are differentiated. Also be aware that some commands expect options to be preceded by a dash while other commands do not. The LPI exams do not concentrate on command options, so don't feel like you need to memorize every obscure option for every command before taking the exams.


5.1.2. Command History and Editing

If you consider interaction with the shell as a kind of conversation, it's a natural extension to refer back to things "mentioned" previously. You may type a long and complex command that you want to repeat, or perhaps you need to execute a command multiple times with slight variation.

If you work interactively with the original Bourne shell, maintaining such a "conversation" can be a bit difficult. Each repetitive command must be entered explicitly, each mistake must be retyped, and if your commands scroll off the top of your screen, you have to recall them from memory. Modern shells such as bash include a significant feature set called command history, expansion, and editing. Using these capabilities, referring back to previous commands is painless and your interactive shell session becomes much simpler and more effective.

The first part of this feature set is command history. When bash is run interactively, it provides access to a list of commands previously typed. The commands are stored in the history list prior to any interpretation by the shell. That is, they are stored before wildcards are expanded or command substitutions are made. The history list is controlled by the HISTSIZE shell variable. By default, HISTSIZE is set to 500 lines, but you can control that number by simply adjusting HISTSIZE's value. In addition to commands entered in your current bash session, commands from previous bash sessions are stored by default in a file called ~/.bash_history (or the file named in shell variable HISTFILE).


Tip: If you use multiple shells in a windowed environment (as just about everyone does), the last shell to exit will write its history to ~/.bash_history. For this reason you may wish to use one shell invocation for most of your work.

To view your command history, use the bash built-in history command. A line number will precede each command. This line number may be used in subsequent history expansion. History expansion uses either a line number from the history or a portion of a previous command to re-execute that command. History expansion also allows a fair degree of command editing using syntax you'll find in the bash documentation. Table 5-1 lists the basic history expansion designators. In each case, using the designator as a command causes a command from the history to be executed again.

Table 5-1. Command history expansion designators

Designator

Description

!!

Spoken as bang-bang, this command refers to the most recent command. The exclamation point is often called bang on Linux and Unix systems.

!n

Refer to command n from the history. Use the history command to display these numbers.

!-n

Refer to the current command minus n from the history.

!string

Refer to the most recent command starting with string.

!?string

Refer to the most recent command containing string.

^string1^string2

Quick substitution . Repeat the last command, replacing the first occurrence of string1 with string2.


While using history substitution can be useful for executing repetitive commands, command history editing is much more interactive. To envision the concept of command history editing, think of your entire bash history (including that obtained from your ~/.bash_history file) as the contents of an editor's buffer. In this scenario, the current command prompt is the last line in an editing buffer, and all of the previous commands in your history lie above it. All of the typical editing features are available with command history editing, including movement within the "buffer," searching, cutting, pasting, and so on. Once you're used to using the command history in an editing style, everything you've done on the command line becomes available as retrievable, reusable text for subsequent commands. The more familiar you become with this concept, the more useful it can be.

By default, bash uses key bindings like those found in the Emacs editor for command history editing. (An editing style similar to the vi editor is also available.) If you're familiar with Emacs, moving around in the command history will be familiar and very similar to working in an Emacs buffer. For example, the key command Ctrl-p (depicted as C-p) will move up one line in your command history, displaying your previous command and placing the cursor at the end of it. This same function is also bound to the up arrow key. The opposite function is bound to C-n (and the down arrow). Together, these two key bindings allow you to examine your history line by line. You may re-execute any of the commands shown simply by pressing Return when it is displayed. For the purposes of Exam 101, you'll need to be familiar with this editing capability, but detailed knowledge is not required. Table 5-2 lists some of the common Emacs key bindings you may find useful in bash. Note that C- indicates the Ctrl key, while M- indicates the Meta key, which is usually Alt on PC keyboards (since PC keyboards do not actually have a Meta key).


Tip: In circumstances where the Alt key is not available, such as on a terminal, using the Meta key means pressing the Escape (Esc) key, releasing it, and then pressing the defined key. The Esc key is not a modifier, but applications will accept the Esc key sequence as equivalent to Meta key.

Table 5-2. Basic command history editing Emacs key bindings

Key

Description

C-p

Previous line (also up arrow)

C-n

Next line (also down arrow)

C-b

Back one character (also left arrow)

C-f

Forward one character (also right arrow)

C-a

Beginning of line

C-e

End of line

C-l

Clear the screen, leaving the current line at the top of the screen

M-<

Top of history

M->

Bottom of history

C-d

Delete character from right

C-k

Delete (kill) text from cursor to end of line

C-y

Paste (yank) text previously cut (killed)

M-d

Delete (kill) word

C-rtext

Reverse search for text

C-stext

Forward search for text


5.1.2.1. Command substitution

bash offers a handy ability to do command substitution. This feature allows you to replace the result of a command with a script. For example, wherever $(command) is found, its output will be substituted. This output could be assigned to a variable, as in the number of lines in the .bashrc file:

$ RCSIZE=$(wc -l ~/.bashrc)

Another form of command substitution is 'command'. The result is the same, except that the back quote syntax has some special rules regarding metacharacters that the $(command) syntax avoids.

5.1.2.2. Applying commands recursively through a directory tree

There are many times when it is necessary to execute commands recursively. That is, you may need to repeat a command throughout all the branches of a directory tree. Recursive execution is very useful but also can be dangerous. It gives a single interactive command the power to operate over a much broader range of your system than your current directory, and the appropriate caution is necessary. Think twice before using these capabilities, particularly when operating as the superuser.

Some of the GNU commands on Linux systems have built-in recursive capabilities as an option. For example, chmod modifies permissions on files in the current directory:

$ chmod g+w *.c

In this example, all files with the .c extension in the current directory are modified with the group-write permission. However, there may be a number of directories and files in hierarchies that require this change. chmod contains the -R option (note the uppercase option letter; you may also use --recursive), which instructs the command to operate not only on files and directories specified on the command line, but also on all files and directories contained under the specified directories. For example, this command gives the group-write permission to all files in a source-code tree named src:

$ chmod -R g+w src

Provided you have the correct privileges, this command will descend into each subdirectory in the src directory and add the requested permission to each file and directory it finds. Other example commands with this ability include cp (copy), ls (list files), and rm (remove files).

A more general approach to recursive execution through a directory is available by using the find command. find is inherently recursive and is intended to descend through directories looking for files with certain attributes or executing commands. At its simplest, find displays an entire directory hierarchy when you simply enter the command with a target directory. (If no action arguments are given to find, it prints each file it finds, as if the option -print were specified.):

$ find src 
...files and directories are listed recursively... 

As an example of a more specific use, add the -name option to search the same directories for C files (this can be done recursively with the ls command as well):

$ find src -name "*.c" 
....c files are listed recursively ...

find can also be used to execute commands against specific files by using the -exec option. The arguments following -exec are taken as a command to run on each find match. They must be terminated with a semicolon (;), which needs to be escaped (\;, for example) since it is a shell metacharacter. The string { } is replaced with the filename of the current match anywhere it is found in the command.

To take the previous example a little further, rather than execute chmod recursively against all files in the src directory, find can execute it against the C files only, like this:

$ find src -name "*.c" -exec chmod g+w {  } \;

The find command is capable of much more than this simple example and can locate files with particular attributes such as dates, protections, file types, access times, and others. While the syntax can be confusing, the results are worth some study of find.


Previous Page
Next Page