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:
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.
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.
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.
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.
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.
The value of PAGER should still be less; the above setting was only temporary.
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.
Since PAGER has been unset, echo won't print anything.
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.
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.
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.
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.
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.
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.
"modifiers" like batch, at, nohup, nice
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:
Expansion patterns are simple, once you see some concrete examples:
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.
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.
Debian Tutorial
[email protected]