No BS Guide to RED HAT Linux: Chapter 4

Living in a Shell


To use Linux--or any Unix-like system, for that matter--you
need to know a few things about shells. A shell is a program
that acts as an intermediary between you and the guts of the
operating system. In a DOS environment, command.com acts as
your shell. Linux shells have more interesting names (like
bash, pdksh, and tcsh), but they do pretty much the same
thing. In addition to translating your commands into
something the kernel can understand and act upon, the shell
adds some important functions that the base operating system
doesn't supply.

Using a Linux shell means working with a command line, which
is much like working from a DOS prompt. You've already been
introduced to the X Windows environment and the GNOME
graphical interface in the previous chapter, but some Linux
tasks can only be done from the command line. The knowledge
of how Linux works that you'll gain in this chapter will
provide the foundation you need to use Linux successfully
and efficiently. Here's a description of the basic features
of all Linux shells, a preview of the functions they
perform, and a rundown of what you'll learn in this chapter.

Prompts - A prompt is a character or string of characters
(such as $ or #) that the shell displays when it is ready to
receive a new command. You'll learn about the different
types of prompts and how to customize them to suit you and
the way you work.

Command resolution - When you enter a command, the shell must
determine which program to run in order to perform that
command. You'll learn how shells do this and how to change
the command resolution process to suit your needs.

Job control - Linux lets you multitask (run more than one
command at a time). You'll learn how to start, list, and
stop tasks; you'll also learn the difference between
foreground and background task execution.

Command history and completion - When you're entering lots of
commands, sometimes you want to repeat the previous command
or issue a similar one. You'll learn how to recall and
modify previously entered commands, as well as find out
about some keyboard shortcuts that can automatically
complete your commands for you.

Wildcards and aliases - Wildcards let you process a whole
bunch of files at once, instead of having to repeat the same
command for each file. You'll learn how to use two types of
wildcards and how to create aliases for commonly used
commands.

Piping and I/O redirection - Sending the output of one
program directly to another program or to a file can save
you time and keystrokes. You'll learn how to pipe program
output (connect programs together) and how to make a program
get its input from a file instead of the keyboard.

This chapter will look at each of these functions in detail
and teach you how to use them to your advantage. But first--a
few shell preliminaries.

Logging In

Unlike DOS, Linux is a multiuser operating system. This means you have to log in before you can use it. After you log in, by default Linux places you in the bash shell. At this point, you can type a command and press enter, and the system will respond. It's just you and the keyboard; the mouse has little to do in this environment. The bash shell prompt just after login. If you've modified your system to start the X Windows GNOME interface automatically at bootup, you can start a windowed bash shell by clicking on the taskbar button that looks like a computer terminal, at the bottom of the screen. (This is analogous to running a Windows 3.x system, where you start in the command.com shell, or launching an MS-DOS prompt after booting Windows 95/98.) In either case, the shell is a text-based environment, with no point-and-click amenities.

The Root User

When you installed Linux, you logged in as root. The root user is called a superuser because it has powers far beyond those of mortal users (and it's not even affected by kryptonite). As root, you can access files and change the system in ways other users cannot. But you can also wipe out your entire hard drive in just ten keystrokes. You can tell when you have root privileges because your prompt ends in # instead of $more on this later in the chapter. Unless you plan to install new software or tweak your system, you should log in to Linux as a user other than root. The problem is, assuming you've followed the steps I've outlined so far, at this juncture there are no other accounts. We'll use this superuser account to change that.

Ex Nihilo: Adding New Users

In the Linux universe, new users do not evolve--they are created by a benevolent superuser. To add a new user account, log in to the root account and enter a command like the one shown here. There's no limit to the number of new users you can add. adduser hermie After using the adduser command, you must assign a password to the new account before it can be used. Use this command to set the password: passwd hermie ... and enter the initial password for hermie when prompted.

What Virtual Consoles Are Good For

Remember that bit about multiple log-ins? Even though you may not have more than one physical console (a monitor plus a keyboard) connected to your PC, you can use virtual consoles to log in simultaneously to more than one account on your system. You can use virtual consoles to perform two activities in parallel. For example, I used one virtual console to write this chapter and another to test the commands as they were introduced. You can even use your mouse to cut and paste text from one virtual console to another. When you start your Linux system and get the log-in prompt, you're looking at console number 1. Go ahead and log in as root here; then press alt-F2. You should then see another log-in prompt. You can log in as user hermie on this console and then press alt- F3 to access a third console or press alt-F1 to return to the first console. Virtual consoles come in particularly handy if you have a long-running task to perform, like installing a big software package from a CD-ROM--you can pop over to another console and log in again to stay productive while your CD-ROM churns away. Note: You don't have to use a different user account for each console. Linux lets you log in to an account multiple times simultaneously. By default, your Linux system already has a bunch of virtual consoles waiting in the wings when you start your system, and pressing alt-Fn at any time will bring the nth one up on your screen. You can also cycle through the consoles with alt-left arrow or alt-right arrow. If you're running in the X Windows environment, there's not much need for virtual consoles because you can accomplish the same thing with multiple shell-prompt windows. But if you really want to use virtual consoles under X Windows, you must use ctrl-alt-Fn to switch to another (full-screen) virtual console. X Windows runs as virtual console 7, so you can switch back with ctrl-alt-F7. Multitasking under Linux isn't really much different from having multiple windows active on a Windows 95/98 or Macintosh system. The major difference is that if you've started multiple consoles, you can see only one at a time on the screen, though the others are still working away behind the scenes.

Stop the System, I Want to Get Off!

If you're ready to cash in your console and call it a day, use the logout command. Entering logout at the command prompt exits your current user account and returns you to the log-in prompt. (The exit command does the same thing as logout.) To log out from multiple consoles, use alt-Fn to switch between consoles and then log out from each one. But note that even if you log out from all of your active consoles, Linux is still running. If you were to power off your machine at this point, a voice from your computer would drone, "You have chosen unwisely!" The floor would shake, and your PC would glow white hot while your hard disk melted into a pool of molten silicon. Just kidding... sometimes the floor doesn't shake, but powering off a running Linux system without using the shutdown command will most certainly cause Bad Things to happen to your hard disk. So if you really want to exit Linux, be sure that you're logged in as the root user and enter the command shutdown -h now You'll see some messages indicating that various subsystems are being shut down, and then the computer will be reset. When you see a message indicating that shutdown is complete, it's safe to turn off your PC. Tip: Pressing ctrl-alt-delete will also safely shut down your Red Hat Linux system. Just remember to power off as soon as you see your PC's normal bootup screen. Note that some other Linux distributions will do a hard reset (which may cause filesystem damage) instead of gracefully shutting down, so don't use ctrl-alt-delete on non-Red Hat systems unless you know it's safe.

Bash (and Other Shells)

Bash, the default Linux shell, is popular and offers lots of advanced features. It combines many of the niceties found in the Bourne shell (the original Unix shell) and other modern shells. But there are alternatives. The Korn shell is popular among many Unix users because it offers a rich scripting (programming) facility. Korn is commercial software, but there is a public-domain (free) version for Linux called pdksh. Another shell that's popular with C language programmers is the C shell, which exists for Linux as tcsh. The CD that comes with this book provides both pdksh and tcsh, and you can try them out by entering their names at your shell prompt. If you decide to make a permanent switch to something other than the default bash shell, you must log in as root and edit the entry for your user ID in the /etc/passwd file. Entries in the /etc/passwd file look like the following example. Just change "bash" at the end of the line to "pdksh" or "tcsh," and you're done. (If you're not familiar with Linux-based text editors, see Chapter 6, "Text Editors.") hermie:x:501:1::/home/hermie:/bin/bash Though there are alternatives, I suggest you familiarize yourself with bash's features first, because bash is the most commonly used Linux shell. In the rest of this chapter, we'll go over the basics of working in the bash shell, so go ahead and log in as user hermie now and follow right along. It'll help a lot to enter the commands as you go, experiment with them on your own, and see the actual output.

Linux Commands

When you enter a command in Linux, you type a command at a prompt and then press enter. Commands can be more than one word--some require switches (which modify the command's behavior ) and/or file names (which tell the command what data to act on). Let's dissect the command shown here: $ ls -l sample.doc

Linux Commands Are Case Sensitive

One of the most important things to remember about entering commands in any Unix environment is that case matters. In DOS, you can type DIR or dir or even DiR and get the same result, but not in Linux. Linux will be quite put out if you type LS instead of ls to list your files. With file names, you have to be even more careful, since nearly identical files (save for capitalization) can exist in the same directory, though they may have completely different contents--Cookie--Recipe and cookie--recipe would appear as distinctly different files to Linux, though they may look pretty much the same to you except for the capital letters. The best rule to follow is this: Almost everything in Linux is lowercase, so avoid capital letters when naming your files.

Command Prompts Can Vary

When the Linux shell is ready for a command, you see a command prompt. Just as in Unlike DOS, which uses only one prompt, Linux's command prompts vary. For example, when you log in as root, your default command prompt is the pound (#) sign, but if you try another log-in as a regular user (like hermie), the prompt changes to a dollar sign ($). Bash uses the different prompts to clue you in to your user privileges. Pay attention to the prompts so you don't inadvertently wipe out important files while logged in to the root account with superuser privileges, for example. It's especially important to mind the prompts if you use the su (switch user) command, which allows you to act temporarily as the root user while you're logged in as a regular user. Watch how the prompt changes in the following example. (User input is in boldface.) $ who am i hermie $ su - root Enter password for root: xxxxxxx # who am i root # exit $ who am i hermie In this example, entering the command who am i tells you who the system thinks you are--hermie. Then the su - root command switches you to the root user (note the prompt change to the pound sign). The exit command exits the root user account and brings you back to hermie; the prompt changes back to a dollar sign. (See Chapter 5, "Important Linux Commands," for more information on the su command.) This example used the prompt and the who am i command to show the logged-in user, but customizing your prompt is a better way to keep track of where you are. For example, the command PS1="\u \$ " changes the prompt so that it displays the user name (\u), followed by the dollar sign (or pound sign, if you're a superuser). You can use other characters to insert the current time, date, or working directory (\t, \d, and \w, respectively). Here's how to use these various options: PS1="\t \$ " yields 09:15:24 $. PS1="\u (\d) \$ " yields hermie (Wed Nov 4) $. PS1="\u (\w) \$ " yields hermie (/home/hermie) $. All you're actually doing here is setting the variable PS1 (prompt string number 1) to a special string of characters. The bash shell interprets the value of the PS1 variable each time it's ready to build the prompt string. In the "Environment Variables" section, you'll learn more about special variables such as PS1 and how to set them automatically each time you log in.

Wildcards

Wildcards come in handy when you want to perform an operation on a group of files. As with DOS or Windows, if you want to delete all your files that start with "jan" and end with "txt," you can use the asterisk (*) wildcard character, as in rm jan*txt, to delete all such files (rm is the command you use to delete files). The * character tells the shell to find any files that begin with "jan" and end with "txt" regardless of the number of characters between. It will even find files with no characters between, like jantxt. Thus, a file named jan- 96.txt would be deleted, as would jantxt. A more restrictive wildcard is the question mark, which matches any single character. Here are some examples of its use: rm jan-8?.txt deletes jan-81.txt and jan-82.txt, but not jan-89b.txt rm jan-95.??? deletes jan-95.txt and jan-95.dat, but not jan-95.db When you use wildcards, the shell finds all matching files and expands the command you entered, so the rm jan-95.* command would be the same as typing rm jan-95.txt jan-95.dat jan-95.db Programmers take note: In Linux, the shell performs wildcard interpretation, and the actual commands (programs) never see the wildcard characters. This provides a convenient and common way for all Linux programs to handle wildcards. In DOS, the program (not the shell) must have the intelligence to handle wildcards. The unhappy result there is that you never know which DOS commands will accept wildcards, and each program may interpret them differently--yuck!

Command History and Editing

Bash remembers what commands you've recently entered so that you can recall and issue them again easily. If you press the up-arrow key, bash places the contents of the previous command on the command line. Repeatedly pressing the up or down arrow navigates through the command history; you can even modify the text in the recalled commands with the left and right arrows, as well as the insert and delete keys, before pressing enter to issue the recalled command.

Command Completion: Linux Can Even Read Your Mind

If you're a lazy typist, you'll love this feature. Let's say you have a directory containing the following files: cars-are-fun cats-are-bad dogs-are-good birds-have-lips Typing rm cat and then pressing the tab key magically expands your command line to rm cats-are-bad matching a file in your current directory that starts with the word cat. The shell looks at what you've typed so far and then checks to see if there is a single file that starts with those characters. If there is, the shell finishes typing that file name for you. If there isn't such a file, or if there is more than one, nothing happens. If multiple files match, a beep will sound. You can then press tab twice to see all the matches, or just keep typing the filename. You still have to press enter, but if you remember this nifty feature, you can save a lot of keystrokes and pretend that the computer is actually reading your mind!

Aliases: Create Meaningful Synonyms for Commands

Defining an alias is another way to minimize your work at the keyboard, and you can also eliminate the need to remember long, awkward commands by creating synonyms that are more meaningful to you. Here are some examples: alias dir='ls -l' alias dogs='find . -name "*dog*" -print' In this example, the first alias tells bash that when you enter dir on the command line, it should actually execute the ls -l command instead. If you're a hard-core DOS user, you could use alias to create DOS-like synonyms for many Linux commands. The second alias lets you enter dogs instead of that long, ugly find command shown above. Don't worry about the ls and find commands right now. Just keep in mind that the alias command can save you some keystrokes and make it easier to remember a command. Undoubtedly you will find other clever things to do with the alias command and add them to your .profile file so they will be available each time you log in. Your .profile file contains a series of commands that bash executes automatically when you log in, similar to autoexec.bat the DOS world.

Redirecting the Input or Output of Linux Commands

Another useful bash feature is its ability to redirect the input and output of Linux commands. You can save the results of a command in a file instead of displaying the results on the screen, or you can feed data from a file to a program instead of entering data from the keyboard. Let's look at redirection first. Imagine a fictitious command called nocats that prompts the user for a number and then waits for that many lines of text to be entered before processing them. (The program looks at each input line and prints only the ones that do not contain the word cat.) You could feed the program by entering the data from the console (bold text is your typed input, normal text is console output): $ nocats 3 Dogs are much better than those other household animals. A cat would never beg for jerky treats. Dogs are pretty stupid, but at least they stick around. Dogs are much better than those other household animals. Dogs are pretty stupid, but at least they stick around. Or using a text editor, you could put all the input data in a file called stuff and feed the nocats program like this: % nocats < stuff Dogs are much better than those other household animals. Dogs are pretty stupid, but at least they stick around. The less-than (<) symbol causes the program to get input from the stuff file instead of waiting for keyboard input. The greater-than (>) symbol, on the other hand, redirects output to a file instead of to the console. Thus, the command % nocats < stuff > bother will cause the nocats program to read its input from one file (stuff) and write it to another (bother), without the keyboard or console entering the picture. Note that the nocats program doesn't know or care about all this redirection. It still thinks it is reading data from the keyboard and writing to the console--but the shell has temporarily reassigned the input and output to files instead of physical devices. To append to an existing file instead of creating a new one, use two greater-than symbols (>>), as in this example: zippity > somefile doodah >> somefile The zippity command runs first, and the output is placed in a new file called somefile. Then doodah runs, and its output is added (appended) to the somefile file. Note: It's important to remember that piping with a single > symbol will wipe out existing data if the output file already exists.

Pipes: Pump a Program's Output into Another Program

Linux provides you with a wide array of utilities to manipulate data. You can search, sort, slice, dice, and transform data stored in files in many different ways. A pipe (also called a pipeline) is a powerful shell feature that allows you to pump the output of one program directly into another. For example, say you have a file with information about a group of people, including a name, age, zip code, and phone number for each person, that looks like this: Roosevelt Tommy 38 54579 555-1212 Nixon Edward 19 37583 246-3457 Roosevelt Freddie 47 11745 674-6972 Lincoln Albert 26 26452 916-5763 If you wanted to find all the Roosevelts and sort them by zip code, you could do it like this: grep Roosevelt people.txt > grep.out sort +3 grep.out rm grep.out Since I haven't introduced the grep and sort commands yet, here's an English translation of what's happening above: Look for lines that contain Roosevelt in the people.txt file and put them in a file named grep.out. Then sort the grep.out file on the fourth column and display the results on the console before deleting the grep.out file. (Yes, it is odd that the +3 flag tells sort to use the fourth column!) But you could avoid creating and deleting the intermediate file (grep.out) by combining the operation into one command like this: grep Roosevelt people.txt | sort +3 The vertical bar tells the shell that the output of the program on the left (grep) should become the input for the program on the right (sort). Behind the scenes, the shell may be issuing the exact same three commands as in the previous example, but you don't really care--you've combined three commands into one. You can have any number of steps in a pipeline, and you can even combine pipes with redirection, as shown here: grep Roosevelt people.txt | sort +3 > sort-results Here, the same thing happens, except that the end result is stored in a file called sort-results.

Listing Processes

Linux is a multitasking operating system, which means that more than one task can be active at once. To find out what tasks are running on your system concurrently, use the command ps -f UID PID PPID STIME TTY TIME COMD hermie 24 1 00:35:28 tty1 0:01 bash hermie 137 24 00:36:39 tty1 0:00 ps -f The output here shows, for each active task, the UID (owning user), PID (process ID), PPID (parent process ID), STIME (when the task started), TIME (how long the task has been active), and CMD (the actual command line used to start the task). If you examine the PIDs and PPIDs, you can see that bash invoked the ps -f command, because the PPID of the latter matches the PID of the former.

Launching Tasks in the Foreground and Background

Suppose you have a long-running task (for example, compiling a large program) that you need to run, but you also want to get some other work done. Linux lets you start a task in the background and keep on doing other things from the command prompt. By adding the ampersand (&) to the end of any command, you can launch it in the background and get your command prompt back right away. For example, cc hugepgm.c > outlist & will start cc (the C compiler) as a background task, executing it in parallel with other tasks on your system. Note: It's a good idea to redirect the output of background tasks to a file, as shown here, since the background task still shares the console with foreground tasks. If you don't, the background task will splash any output it might produce all over your screen while you're editing a file or typing another command. If you start a long-running task and forget to add the ampersand, you can still swap that task into the background. Instead of pressing ctrl-C (to terminate the foreground task) and then restarting it in the background, just press ctrl-Z after the command starts, type bg, and press enter. You'll get your prompt back and be able to continue with other work. Use the fg command to bring a background task to the foreground. You might wonder why you'd ever want to swap programs between the foreground and background, but this is quite useful if for example you're doing a long-running compile using a text editor and you need to issue a quick command at pop out to the shell prompt., issue a quick command, and go back to editing. While the compilation is runningFrom inside the editor, you could press ctrl-Z and then enter the bg command to put the compilereditor in the background. Then do your thing at the shell prompt and enter the fg command. Presto--your editor reappears on the screen just the way you left it! to return the compiler task to the foreground. The ctrl-Z trick also works with the Emacs text editor and the Pine email program. You can suspend either program and then return to your work in progress with the fg command. Of course, in the X Windows environment, all these unnatural gyrations are not necessary. Just start another shell window and run the other command there. You can watch both processes running in separate windows at the same time, and you don't have to worry about adding ampersands, piping output to files, or keeping track of foreground versus background processes.

Stop That Task!

Although it's unfortunate, some tasks are unruly and must be killed. If you accidentally entered the (fictitious) command seek--and--destroy & you'd have a background task doing potentially nasty things. Pressing the ctrl-C key would have no effect, since it can terminate only a foreground task. Before this rogue eats your system alive, issue the ps -f command to find out the process ID (PID) of the seek--and--destroy task: ps -f UID PID PPID STIME TTY TIME COMD hermie 24 1 00:35:28 tty1 0:01 bash hermie 1704 24 00:36:39 tty1 0:00 seek--and--destroy Note that the offender has a PID of 1704 and then quickly issue the command kill 1704 to terminate the background task. You can terminate any active task with the kill command, which sends a "terminate gracefully" signal to the running task that allows it to do any necessary cleanup, close files, and so on before giving up the ghost. Occasionally, though, a task will not respond to the kill command, either because a program has become disabled or is coded specifically to ignore it. Time for the heavy artillery. Adding the -9 flag to the kill command, as in kill -9 1704 basically sends the "die you gravy-sucking pig" signal to the running task and forces it to shut down immediately without any chance to do cleanup. Use this flag only as a last resort, since it could cause work in progress (by the soon-to-be-killed task) to be lost.

Environment Variables

Environment variables in the bash shell help you in several ways. Certain built-in variables change the shell in ways that make your life a little easier, and you can define other variables to suit your own purposes. Here are some examples of built-in shell variables: - PS1 defines the shell's command-line prompt. - HOME defines the home directory for a user. - PATH defines a list of directories to search through when looking for a command to execute. To list the current values of all environment variables, issue the command envset or list a specific variable with the echo command, prefixing the variable name with a dollar sign (the second line shows the result of the echo command): echo $HOME /home/hermie You've already learned how to customize your shell prompt with the PS1 variable. The HOME variable is one you shouldn't mess with, because lots of programs count on it to create or find files in your personal home directory.

Understanding the Path Variable

As in DOS, the shell uses the PATH variable to locate a command. PATH contains a list of directories separated by colons: echo $PATH /bin:/usr/bin:/usr/local/bin When you enter a command, the shell looks in each of the directories specified in PATH to try to find it. If it can't find the command in any of those directories, you'll see a "Command not found" message. If you decide to put your own programs in a bin directory under your home directory, you'll have to modify the path to include that directory, or the system will never find your programs (unless you happen to be in that directory when you enter the command). Here's how to change your PATH variable so it includes your personal bin directory: PATH=$PATH:$HOME/bin So if PATH was set to /bin:/usr/bin:/usr/local/bin beforehand, it would now have the value /bin:/usr/bin:/usr/local/bin:/home/hermie/bin. Creating Your Own Shell Variables If you are a programmer, you'll find it handy to create your own shell variables. First issue the command code=$HOME/projects/src/spew and then, regardless of what directory you are in, you can issue cd $code to pop over quickly to the directory containing the source code for that way-cool spew program you're developing. (The cd command means "change directory.") A variable assignment like this will work just fine, but its scope (visibility) is limited to the current shell. If you launch a program or enter another shell, that child task will not know about your environment variables unless you export them first. Unless you know for sure that an environment variable will have meaning only in the current shell, it's a good idea to always use export when creating variables to ensure they will be global in scope--for example, export PS1="\u \$ " export code=$HOME/projects/src/spew And be sure to add these commands to your .profile file so you won't have to retype them each time you log in.

How to Get Help

Need help figuring out what a command is supposed to do? In an operating system with strange-sounding commands like awk, grep, and sed, it's not surprising. The man command (short for manual) is a source of online help for most Linux commands. For example, you can enter man grep to learn all the secrets of the very useful grep command. (For a summary of the most-used Linux commands, see Chapter 5, "Important Linux Commands.") If man claims no knowledge of the command in which you're interested, try help instead. This command will list all the built-in bash commands with a brief syntax summary. Another help format called info is more powerful, since it provides hypertext links to make reading large documents much easier, but not all documentation is available in info format. There are some very complete info documents on various aspects of Red Hat (especially the portions from the GNU project). To try it out, use the info command without any arguments. It will present you with a list of available documentation. Press h to read the help for first-time users, or use the tab key to move the cursor to a topic link and then press enter to follow the link. Pressing p returns you to the previous page, n moves you to the next page, and u goes up one level of documentation. To exit info, press q.

The GNOME Help Browser

If you're running X Windows with the GNOME interface (the default when you install Red Hat Linux), you can access the man and info pages much more easily. Just click on the taskbar button with the big question mark, and you'll launch the GNOME Help Browser. From there, you can browse a catalog of man or info pages, along with special help files for the GNOME interface.

Copyright 2000, Bob Rankin, All Rights Reserved