[ previous ] [ Contents ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ 14 ] [ 15 ] [ 16 ] [ 17 ] [ 18 ] [ A ] [ B ] [ C ] [ D ] [ next ]

Debian Tutorial
Chapter 6 - Using the shell


6.1 Environment variables

Every process has an environment associated with it. An environment is a collection of environment variables. A variable is a changeable value with a fixed name. For example, the name EMAIL could refer to the value [email protected]. The value can vary --- EMAIL could also refer to [email protected].

Since your shell is a process like any other, it has an environment. You can view your shell's environment by entering the printenv command. Here's some example output:

     PAGER=less
     HOSTNAME=icon
     MAILCHECK=60
     MOZILLA_HOME=/usr/local/lib/netscape
     PS1=$ 
     USER=hp
     MACHTYPE=i486-pc-linux-gnu
     EDITOR=jed
     DISPLAY=:0.0
     LOGNAME=hp
     [email protected]
     SHELL=/bin/bash
     HOSTTYPE=i486
     OSTYPE=linux-gnu
     HISTSIZE=150
     HOME=/home/hp
     TERM=xterm-debian
     TEXEDIT=jed
     PATH=/home/hp/local/bin:/usr/sbin:/home/hp/.bin:/home/hp/local/bin:/usr/sbin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:.
     _=/usr/bin/printenv

On your system, the output will be different, but similar.

Environment variables are one way to configure the system. For example, the EDITOR variable lets you select your preferred editor for posting news, writing email, and so on. The HISTSIZE variable tells Bash how many command lines to keep in its history; you can return to that many command lines with the up arrow key.

Setting environment variables is simple. Once you learn how, you'll probably want to set them automatically whenever you log on; see Customizing the shell, Chapter 9 for instructions.

For practice, try customizing your shell's prompt and your text file viewer with environment variables:

  1. man less

    View the online manual for the less command. In order to show you the text one screenful at a time, man invokes a pager which shows you a new page of text each time you press the space bar. By default, it uses the pager called more.

    Go ahead and glance over the man page for less, which is an enhanced pager. Scroll to a new page by pressing space; press q to quit. more will also quit automatically when you reach the end of the man page.

  1. export PAGER=less

    After reading about the advantages of less, you might want to use it to read man pages. To do this, you set the environment variable PAGER.

    The command to set an environment variable within bash always has this format: export NAME=value. If you happen to run tcsh or another C Shell derivative, the equivalent command is setenv NAME value.

    export means to move the variable from the shell into the environment. This means that programs other than the shell will be able to access it.

  1. echo $PAGER

    This is the easiest way to see the value of a variable. $PAGER tells the shell to insert the value of the PAGER variable before invoking the command. echo echoes back its argument: in this case, the it echoes the current PAGER value, less.

  1. man more

    Read the more manual. This time, man should have invoked the less pager.

    less has lots of features more lacks. For example, you can scroll backward with the b key. You can also move up and down (even sideways) with the arrow keys. less won't exit when it reaches the end of the man page; it will wait for you to press q.

  1. PAGER=more man more

    If you want a different setting temporarily, you can put a new value in effect for the current command line only. Put the NAME=value at the start of the command line, followed by the command to execute. Be sure to omit export.

    You can try out some less-specific commands, like b, to verify that they don't work with more and you are indeed using more.

  1. echo $PAGER

    The value of PAGER should still be less; the above setting was only temporary.

  1. unset PAGER

    If you don't want to specify a pager anymore, you can unset the variable. man will then use more by default, just as it did before you set the variable.

  1. echo $PAGER

    Since PAGER has been unset, echo won't print anything.

  1. PS1=hello:

    Just for fun, change your shell prompt. $ should become hello:.

    export is not necessary, because we're changing the shell's own behavior. There's no reason to export the variable into the environment for other programs to see. Technically, PS1 is a shell variable rather than an environment variable.

    If you wanted to, you could export the shell variable, transforming it into an environment variable. Then other programs could see it: specifically, the children of the current shell process. The next section explains this.


6.1.1 Parent and child processes

All processes come from an earlier process, called their parent process. [10] The ps command is a useful tool for exploring processes, and it can be used to examine parent-child relationships.

  1. ps f

    This command asks to see a list of processes belonging to you, in a format that shows how processes are related.

ps f might produce output like this:

     $ ps f
       PID  TT STAT   TIME
      7270  p5 S      0:00 bash
     15980  p5 R      0:00  \_ ps f
     19682  p4 S      0:00 bash
     15973  p4 S      0:00  \_ man ps
     15976  p4 S      0:00      \_ sh -c /bin/gzip -dc '/var/catman/cat1/ps.1.gz' | { export MAN_PN LESS; MAN_PN='ps(1)'; LESS="$LESS\$-Pm\:\$i
     15977  p4 S      0:00          \_ /bin/gzip -dc /var/catman/cat1/ps.1.gz
     15978  p4 S      0:00          \_ sh -c /bin/gzip -dc '/var/catman/cat1/ps.1.gz' | { export MAN_PN LESS; MAN_PN='ps(1)'; LESS="$LESS\$-Pm\
     15979  p4 S      0:00              \_ less
     $

Here you can see that I have a number of processes running, including two shells. The shells have child processes: shell process 7270 has child process 15980 (ps f) and shell 19682 has child process 15973 (man ps). man ps has in turn invoked a complex set of subprocesses in order to display a man page. Don't worry about what these subprocesses do for now.

Parents and children have a complex relationship. Most of the time, when a parent dies the child will die as well. So you can kill a whole set of processes --- for example, all the man ps children in the above example --- by killing the parent process, 15973.

Children inherit the environment variables of their parents, and some other attributes such as the current working directory.

When a shell runs a command, it spawns the command as a child process. So the man command inherits the shell's environment; if you've set the PAGER variable, man will be able to see it.

If you fail to export a variable, only the shell itself will see it, and it will not be passed on to children such as man.


6.2 Where commands live: the PATH variable

When you type a command into the shell, it has to find the program on your hard disk before executing it. If the shell had to look all over the disk, it would be very slow; instead, it looks in a list of directories contained in the PATH environment variable. This list of directories makes up the shells' search path; when you enter a command, it goes through each one in turn looking for the program you asked to run.

You may need to change the PATH variable if you install programs yourself in a nonstandard location.

The value of PATH is a colon-separated list of directories. The default value on Debian systems is:

     /usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

This value is defined in the file /etc/profile and applies to all users. You can easily change the value, just as you can change any environment variable.

If you type the command ls, the shell will first look in /usr/local/bin; ls isn't there, so it will try /usr/bin; when that fails, it will check /bin. There it will discover /bin/ls, stop its search, and execute the program /bin/ls. If /usr/bin/X11/ls existed (it doesn't, but pretend), it would be ignored.

You can see which ls the shell is going to use with the type command. type ls will give you the answer /bin/ls --- try it yourself.

Try asking where type itself resides:

     $ type type
     type is a shell builtin

type isn't actually a program; it's a function provided by the shell. However, you use it just like an external program. [11]

There are a number of commands like this; type man builtins to read the man page describing them. In general, you don't need to know whether a command is a builtin or a real program; however, builtins will not show up in the output of ps or top since they aren't separate processes. They're just part of the shell.


6.3 Aliases and shell functions

If you use the same command often, you might get tired of typing it. bash lets you write shorter aliases for your commands. You can also write shell functions, which are custom commands made up of several other commands.

Say you always use the --almost-all and --color=auto options to ls. You quickly get tired of typing ls --almost-all --color=auto. So you make an alias:

     alias myls='ls --almost-all --color=auto'

Now you can type myls instead of the full command. To see what myls really is, run the command type myls. To see a list of aliases you've defined, type simply alias on a line by itself.

Shell functions are a little more flexible than aliases. An alias simply substitutes a longer command when you type a shorter one. Functions let you use a series of commands to perform some action.

First let's see how a shell function could be used in place of the above alias:

     myls() {
         ls --almost-all --color=auto $*
     }

The above is called a function definition, because it gives a function name (myls), then defines the meaning of the name (some commands to execute). To define a function, write its name, followed by (). Then include the commands to execute inside braces ({}). The portion inside braces is known as the body of the function.

The arguments to the function can be referred to as $*. So if you type:

     myls /usr  /etc

$* will be /usr /etc, the two arguments. If there are no arguments, $* will be empty.

You can also refer to the arguments by number. So $1 in the function body would be replaced by /usr, and $2 would be replaced by /etc. Type in this function (you can type it at the shell prompt; hit return after each line):

     print_arguments() {
         echo "First argument:   $1"
         echo "Second argument:  $2"
         echo "All arguments:    $*"
     }

You can verify you entered the function definition correctly with the type command; type print_arguments should say:

     print_arguments is a function
     print_arguments () 
     { 
         echo "First argument:   $1";
         echo "Second argument:  $2";
         echo "All arguments:    $*"
     }

Try the function out. If you enter print_arguments one two it will display:

     First argument:   one
     Second argument:  two
     All arguments:    one two

There are many more complex things you can do in a shell function; you're limited only by your imagination. For more, see Introduction to shell scripting, Section 16.1.


6.4 Controlling input and output

Stdin, stdout, pipelines, and redirection

Every process has at least three connections to the outside world. The standard input is one source of the process's data; the standard output is one place the process sends data; and the standard error is a place the process can send error messages. (These are often abbreviated stdin, stdout, and stderr.)

The words `source' and `place' are intentionally vague. These standard input and ouput locations can be changed by the user; they could be the screen, the keyboard, a file, even a network connection. The user can specify which locations to use.

When you run a program from the shell, usually standard input comes from your keyboard and standard output and error both go to your screen. However, you can ask the shell to change these defaults.

For example, the echo command sends it output to standard output, normally the screen. But you can send it to a file instead, with the output redirection operator, '>'. For example, to put the word "Hello" in the file myfile:

     echo Hello > myfile

Use cat or your text file pager (more or less) to view myfile's contents.

You can change the standard input of a command with the input redirection operator, '<'. For example, more < myfile will display the contents of myfile. This is not useful in practice; for convenience, the more command accepts a filename argument. So you can simply say more myfile and the effect will be the same.

Under the hood, more < myfile means that the shell opens myfile, then feeds its contents to the standard input of more. more myfile, without the redirection operator, means that the more command receives one argument, myfile, opens the file itself, and then displays the file.

There's a reason for the double functionality, however. For example, you can connect the standard output of one command to the standard input of another. This is called a pipeline, and it uses the pipe operator, '|'.

Perhaps you want to see the GNU General Public License in reverse. To do this, you use the tac command (it's cat, only backward). Try it out:

     tac /usr/doc/copyright/GPL

Unfortunately, it goes by too quickly to read. So you only get to see a couple of paragraphs. The solution is a pipeline:

     tac /usr/doc/copyright/GPL | more

This takes the standard output of tac, which is the GPL in reverse, and sends it to the standard input of more.

You can chain as many commands together as you like. Say you have an inexplicable desire to replace every G with Q; for this you use the command tr G Q, like this:

     tac /usr/doc/copyright/GPL | tr G Q | more

You could get the same effect using temporary files and redirection. For example:

     tac /usr/doc/copyright/GPL > tmpfile
     tr G Q < tmpfile > tmpfile2
     more < tmpfile2
     rm tmpfile tmpfile2

Clearly a pipeline is more convenient.


6.5 Specifying how and when to run commands

"modifiers" like batch, at, nohup, nice


6.6 Filename expansion ("Wildcards")

Often you want a command to work with a group of files. "Wildcards" are used to create a filename expansion pattern: a series of characters and wildcards that expands to a list of filenames. For example, the pattern /etc/* expands to a list of all the files in /etc [12]. * is a wildcard which can stand for any series of characters, so the pattern /etc/* will expand to a list of all the filenames beginning with /etc/.

This filename list is most useful as a set of arguments for a command. For example, the /etc directory contains a series of subdirectories called rc0.d, rc1.d, etc. Normally to view the contents of these, you would type:

     ls /etc/rc0.d /etc/rc1.d /etc/rc2.d /etc/rc3.d /etc/rc4.d /etc/rc5.d /etc/rc6.d /etc/rcS.d

This is tedious. Instead, you can use the ? wildcard:

     ls /etc/rc?.d

/etc/rc?.d expands to a list of filenames which begin with rc, followed by any single character, followed by .d.

Available wildcards are:

*
Matches any group of 0 or more characters
?
Matches exactly one character
[...]
If you enclose some characters in brackets, the result is a wildcard which matches those characters. For example, [abc] matches either a, or b, or c. If you add a ^ after the first bracket, the sense is reversed; so [^abc] matches any character that is not a, b, or c. You can include a range, such as [a-j], which matches anything between a and j. The match is case sensitive, so to allow any letter, you must use [a-zA-Z].

Expansion patterns are simple, once you see some concrete examples:

*.txt
This will give you a list of any filename which ends in .txt, since the * matches anything at all.
*.[hc]
This gives a list of filenames which end in either .h or .c.
a??
This gives you all three-letter filenames that begin with a.
[^a]??
This gives you all three-letter filenames that do not begin with a.
a*
This gives you every filename that starts with a, regardless of how many letters there are.

6.7 Interactive/non-interactive

Bash has two different modes: interactive and non-interactive. Interactive means you can type into it, and have it do things for you. Non-interactive shells interpret shell scripts, similar to DOS batch files. You give it a list of commands to carry out, and it goes and does them, but without your intervention. You don't see all the commands being typed in, Of course any output will be recorded somewhere (the standard output, or stdout, normally the screeen or a log file). We will get more into non-interactive shells a little later on.


6.7.1 Interactive shells

Interactive shells will take a very long time for one to master, just because they're so powerful --- you'll probably never learn everything! There is just so much out there that a shell can do, and of course it's always changing. We will talk about bash here, and some basic commands that will make your life with a shell easier. In bash, one can have several different things going on all at once, and this can get confusing.

A shell is a Line Oriented or command line environment. The shell will always prompt you with a prompt, whenever it is waiting on you to do things. The default debian prompt is a $. At the $ prompt is where you can type in commands to tell linux to do things, it can be a program name, or it can be a "builtin" command that the shell provides for your convenience.


[ previous ] [ Contents ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ 14 ] [ 15 ] [ 16 ] [ 17 ] [ 18 ] [ A ] [ B ] [ C ] [ D ] [ next ]

Debian Tutorial


17 June 2006

Havoc Pennington [email protected]