The Linux Graphical User Interface
What follows is a brief overview of how to use Linux from the command line using a terminal window and is usually that part most people find most intimidating. In fact most people seem to believe that this is the only way to use a Linux system which may explain why it scares them away. Overwhelmed by what they perceive to be an impossibly difficult interface, these folks flock to the more colorful and, presumably, easier graphical interface offered by Microsoft Windows and the Apple Mac.
It's only later, after the user has gained some skill, that the power and ease of management of Linux becomes desirable. Yet Linux provides the same graphical interface as their less competent competitors with all the same features and capabilities and with many more configurable options. It's even possible to mimic the look and feel of Windows and Macs so that the user can work with his computer in a familiar environment. The choice to work exclusively in the graphical environment is up to the user. If the user wants to get adventurous, there is always the command line and the command line is the best way to do the really cool stuff.
Your Login Environment
To access the Linux system you have to have an account. The account will
have a login name and a password, you will use these to login. Once the login is accepted Linux will set your environment and execute any commands it finds your .bash_profile file (assuming your shell is bash . If the shell is sh or ksh .profile will execute, if it's csh .cshrc
will be executed). When all is ready Linux will present you with a
prompt, usually the dollar sign ($). The prompt tells you that you can
enter commands.
To see the environment:
env
Or
set
The system will show you a list of variables that affect the way your
commands will be executed. Since they are variables, you can change
them to any value you like, although some settings may not work the way
you expect.
The first file Linux executes after all of this is the .bash_profile (notice that there is a dot at the beginning of the file name .
You can put any shell command in
this file. Normally Linux will execute the commands in the system setup file to provide a basic environment. This file is called, /etc/bash_profile
. This file is going to run regardless of anything else but you can
change whatever that file does by adding commands to your personal .bash_profile file. Some of the things you might want to change are:
PS1 This is the prompt ($ by default)
HOME This can be any directory but is usually your "HOME" directory
PATH This is where Linux looks to find executable files
Notice that these are variables and they set the environment. They are,
therefore, called environment variables. All environment variables are
written as all caps (upper-case only). These variables are always
available and can be used within shell programs. When any variable
(environment or otherwise) is used it will be prefixed by the dollar
sign ($) so the environment variable PS1, for instance, is referred to
as $PS1.
To give a variable a value, the dollar sign is not used, instead you just use its name:
PS1='$HOSTNAME ${PWD#*}> '
Notice that there are no space between the variable name and whatever is
being assigned to it. The quotes are required to make sure everything you
are assigning is properly included in the variable. An interesting aside
here, the single quotes (') are used to pass the quoted string to the shell
with no parsing at all. The shell will strip off the quotes and then
interpret the command string. With the double quotes (") the string would
have be interpreted (parsed) before the shell got it and would've have seen
something entirely different. These two kinds of quotes will confuse you for
a while so experiment to see how they affect the way the shell works.
You can also add or change aliases . An alias
is a command that executes other commands. An alias is useful if you
want to modify that way a standard command works. An alias looks like
this:
alias dir='ls -lA|grep "^d"'
An alias is handy since you can quickly create your own
commands. An alias is also executed before any command in your PATH so
it takes precedence over existing commands of the same name (so be
careful with alias names!). In the example above, alias dir='ls -lA|grep
"^d"' creates a command called, dir and assigns it a value that will
produce the same output as the ls -lA that's piped into grep which
will return only strings that begin with a "d" character. It just lists directories.
You can also create a "shell function". A shell function is a complete
shell program within another shell program (a shell program is called a
script ). A shell function can be used as a sub-routine
which means that it can be called within a script based on whatever
condition you specify. This gives a shell script the power and
flexibility of a real programming language. A function looks like this:
checkname()
Here the function is the function name followed by empty parentheses.
On the next line is the left curly brace. This starts the function
definition. Then there's some regular shell commands and then the right
curly brace that ends the function definition. Now it's a sub-routine
can be called from anywhere within the main script. function can also be executed from
the commandline. To see what functions are defined type functions at the
prompt. To see aliases, type aliases.
Using these features you can create a very sophisticated program that
executes every time you login. You should experiment with the .bash_profile
shell script to see how you can change your environment and tailor it
to your needs.
After making a change to the .bash_profile you will want to execute it to see if everything works:
. .bash_profile
That's a dot (.) followed by a space and then .bash_profile. The first dot
causes the shell to execute .bash_profile file as if you had just logged in.
If you have used Windows or DOS you will notice some differences in the
way things are done. A directory uses the forward slash character (/)
to separate directory elements under Linux instead of the backslash
(\). The cd command by itself will return you to your HOME directory
rather than just display the current directory.
There are no drive letters like C: or D:. Linux sees everything as a
directory beneath the root (/) directory regardless of where it is on a
disk or even which disk it may be on if you have more than one physical
disk. Every part of a command must
be separated from every other part by a space or tab. Linux uses the
minus sign character (-) to include a command option while Windows and
DOS use the slash character (/). Linux is case-sensitive.
A command like LS is different than ls. Windows and DOS change
everything to upper-case and can't tell the difference between upper
and lower case. Linux has an on-line manual that explains every command
in detail.
There are many other differences, large and small, between Windows/DOS
and Linux, so much of what you may have understood from Windows and DOS
may not be that helpful when using Linux. Past experience is helpful of
course, but there's still much to learn.
A Linux command (actually a shell command
since the shell is the mechanism used to parse and process commands)
sees a command as a collection of pieces. The first piece is the
command itself. Following the command there can be arguments. A command can be something like:
ls
an argument to ls might be an option that changes they way it works:
ls -lA
An option is always prefixed by the minus sign character (-) and is
used to modify the command. There can be other arguments like a file or
directory:
ls -lA /etc
In the example above there are three arguments: the command itself, the
options and the directory (the object of the command). The command is
an argument because we are actually asking the shell to process the
command (the shell is the subject). Because the entire command line has
a subject, a "verb" (the command and its options) and an object, it has
a "syntax" or "grammar" and the shell is very picky about how you talk
to it.
Since the usual way to number things when speaking to a computer is to
begin with zero, the first argument is zero (0), the next is one (1)
and then two (2) and so on. What's particularly useful about this is
that these arguments are also variables. This makes it possible to
refer to each part of a command as a series of variables beginning with
zero:
$0 $1 $2 ... $n
So in the example above, ls is variable $0, the option -lA is $1 and the directory, /etc
, is $2. These kinds of variables are called "positional parameters"
and are defined by their position on the command line. The shell knows
many kinds of variables and any of them can be used in a shell script.
This capability makes it possible to write shell scripts that can
"know" just about anything about the world they live in. Because of
this flexibility, almost all of the Linux configuration is constructed
using shell scripts.
The System Configuration Environment
Since the Linux system is configured almost entirely by shell scripts,
it's fairly easy to examine and even change the system by modifying
these scripts. Most of the major Linux system configuration files are
located in the /etc directory. Within this directory are lots of
configuration scripts and sub-directories containing still more
scripts. Many of these scripts depend on still other scripts and,
often, various non-script configuration files (often named with a .conf
extension).
There are several directories that contain information
Linux needs to start and run most of the network and system services
. A service in this case is one or more programs that provide some
feature required to make the system useful. A service will often refer
to some other service so that configuring one can affect another.
The location of system files will vary depending on the distribution
and version of the UNIX or Linux you're using. /etc/init.d is common
but so is /etc/rc.d/init.d and the /etc/xinetd.d directory can be in other
places than what I'm describing here (a Redhat Linux system). Some
systems also use an /etc/inetd.conf file to manage network services.
The log file locations can also vary as well as the location of the
sendmail files and directories. You may have to poke around to find
everything but regardless of the actual locations, their purpose is the
same.
Two directories in particular are essential. The /etc/xinetd.d
directory contains files that instruct some service on how it should
operate. These are not scripts but rather lists of options a service
uses to operate. The /etc/init.d directory contains a collection of
shell scripts that are used to start and stop various services
(typically, servers like apache or DNS). These are scripts that test
the current environment for some odds and ends and then start a program
based on that environment. In both of these directories the programs
that the files and scripts refer to are called,
Daemons
A somewhat complex example is the email daemon. This daemon is called sendmail
and is used to process all the email services. When the system boots it
will start all the daemons you have activated. If sendmail is
configured to run, the boot process will run the script
/etc/init.d/sendmail and pass it the option to start:
/etc/init.d/sendmail start
The sendmail script will first perform a bunch of checks to see how it
should behave. If these checks pass, the script will start the sendmail
daemon using whatever options you have configured.
During all of this, the script or sendmail itself will refer to
configuration files located in the /etc/mail directory. This directory
contains the files that actually determine how sendmail will work. Most
of this information will be in the etc/mail/sendmail.cf file. Sendmail
reads this file every time it starts so if you change something in this
file you have to re-start sendmail. Most likely you will never even
look at any of these files, but it's good to know where the are and
what they do.
To see what daemons are configured to start when the machine boots:
chkconfig --list
This will display a listing of all the currently configured daemons.
The list has the daemon on the left-most column and the various "run
levels" in which it is supposed to run. A run level is a point in the
boot process. Unlike Windows or Macs, Linux doesn't have to boot all
the way before you can begin using it. The boot can be in stages.
These stages, or run levels, provide some capability unique to that run
level. The run levels are:
The start up script for sendmail in /etc/init.d/sendmail will check to
see if the daemon is enabled. If so the script will continue starting
sendmail. If not it will just quit and do nothing.
To see which daemons get started and if there were start up problems,
you can view the system log file located in /var/log/messages or
/var/log/maillog (for sendmail). The Linux system logs just about
everything that happens so you can check these logs if there is a
problem or you suspect something is amiss. There are several ways to view a file. Since most of the
files you want to examine are plain text almost any configuration file
can be viewed. The viewers are:
more
To view the system log file, then, try:
more /var/log/messages
You can just view the last few lines of a file:
tail /var/log/maillog
Or maybe view only the first few lines:
head /var/log/lastlog
Since you will probably want to view some of these files fairly often, you might benefit
from creating an alias in your . bash_profile file:
alias syslog='tail -200 /var/log/messages'
alias maillog='tail -100 /var/log/maillog'
Now you just have to type the alias name to view the file.
The vi Editor
vi .bash_profile
This will "open" the file and display the first line of the file. If
it's a new file there won't be a first line so vi will display the
tilde character (~). There are several ways to enter new text depending
on where the cursor is located. Normally the cursor will be positioned
on the first character of the first line.
The vi editor is a "screen editor" meaning that it displays one screen
full of the file at a time and also that that can move around within
that screen to edit stuff. To do all this it uses commands, usually of
one letter. There are several way to access these commands. The
simplest commands are those having the simplest function.
Notice that these commands use another character at the beginning of
the command. The colon character (:) is used to tell vi that the action
applies to the entire file in most cases. The slash character is used
to specify some string of characters ("words"). This hints at the most
basic functions of vi, but to actually edit the file you have to use
another kind of command. These commands don't use the colon (:), you
just enter the command:
These commands are used when you are actually editing a file. When in the text entry mode (a,i,o,O) you have to hit the Esc key to exit the editing mode. There's lots of other commands but these are enough to get you started.
Now we can edit the .bash_profile file (letters that are bold are commands you will enter:
vi .bash_profile
:$
a
alias syslog='tail -100 /var/log/messages'
Hit the Esc Key here ...
At this point you've added some text to the bottom of the file. If you write this file to disk and then quit,
:!wq
this file will now be permanently stored on the disk.
Now lets add something else:
vi .bash_profile
Hit the Esc Key here and then write and quit:
:wq!
You can edit, save and edit again as often as you want. Since this is
your startup file that will execute every time you login, let's execute
it now to see what it does:
. .bash_profile
Notice the dots (.). They're important, they tell the shell to execute
this file and preserve the settings it may have changed. This technique
is necessary because the shell will usually execute a copy of itself to
run the script. This copy will execute and then disappear returning
control back the original shell. Whatever that copy (sub-shell) does is
forgotten as soon as it finishes so any settings it may have used are
also forgotten. The dot (.) command tells the original shell to not use
a sub-shell but to run the script itself. Doing it this way means that
the environment settings won't be forgotten but will instead become
part of the original shell. Sounds complicated but it makes sense once
you've used it a few times.
So the dot command above will replace the existing environment with the
settings added to the .bash_profile file. Now you can see the effect of the
changes. If you don't like the changes, edit the .bash_profile file again,
change stuff, write and quit vi and then run the dot command again.
Any changes to the shell's environment while in a sub-shell will be
lost when the sub-shell finishes. To preserve changes to the
environment use the export
directive to force the change to exist in all subsequent sub-shells. If
export is used in the .bash_profile file then that environment change will
persist in all the sub-shells. Any changes to the shell's environment
while in a sub-shell will be lost when the sub-shell finishes. To
preserve changes to the environment use the export directive to force
the change to exist in all subsequent sub-shells. If export is used in
the .bash_profile file then that environment change will persist in all the
sub-shells."
If you enter the .bash_profile entries above and run the dot
command on .bash_profile, you will immediately see the difference. The prompt
(the PS1 variable) will be different, you can just type, syslog to see the last 100 lines of the system log file /var/log/messages or maillog to see the /var/log/maillog file. Type dir (the
alias you created).
It's important to understand that UNIX (and, later, Linux) has always
been a multi-user and multi-tasking operating system. This means that
many users can be executing many commands at the same time. To keep
everything straight, each user is given a copy of the shell at login.
This copy belongs to that user and that user can modify the environment
using the .bash_profile startup file. The shell that belongs to a user can
"spawn" (start) sub-shells and each sub-shell will belong to the
original login shell for that user. This makes the multi-user,
multi-tasking capability possible. Understanding this design is
necessary to effectively manage your environment.
A shell script is a plain text file that contains commands that can be
executed as a group rather than one at a time from the command line.
Not only is a script convenient, it's extremely powerful since you can
construct some very complex commands specific to your needs. The
.bash_profile file discussed earlier is a shell script but it doesn't really
do much until you makes some changes to it. Once you have a working
script, all you have to do to execute it is change its permissions and then just type the file name of the script to execute its commands.
A file or directory will always have some permissions
that determine what kind of file it is and who can use it. These
permissions assume three classes of possible users: the owner of the
file, the group of users to which the owner belongs, and everyone else.
Each of these classes of users will have three possible kinds of
access: Read, Write and Execute. Read permission means that the file
can viewed, write permission means that the file can be modified and
execute permission means that the file is a program or script that can
be run as a command.
Type
Owner
Group
Others
File
read
write
execute
read
write
execute
read
write
execute
1/0
1/0
1/0
1/0
1/0
1/0
1/0
1/0
1/0
If a bit is set to one in a bit position in the table, it has the decimal
value shown. If more than one bit position is set to 1 then you add those
bits together. If bit position 0 (decimal value 1) and bit position 6
(decimal value 64) are set to one and all the others are set to 0 then add
64 and 1 together for a decimal value of 65. All we care about are the bit
positions that are set to 1 and we just add their decimal values together.
This kind of Binary Coded Decimal is used to set file and directory
permissions and other stuff like a netmask or IP addresses. A "bit-mapped"
value is different in that a bit set to 1 is used to "flag" something as in
a IP packet or enable something in a configuration file.
Now, where was I ...
binary
1
1
1
1
0
1
1
0
1
octal
7
5
5
To provide read, write and execute permissions to the owner, use an
octal 7. For read and execute permission use octal 5. A shell script
will usually have at least access level 5.
To modify a file's permissions, use the chmod command:
chmod 755 file_name
Each class of user is identified using a 1 (one) for the kind of
permission being granted. If that permission is one then access is
granted, if it is empty (zero) then permission is denied.
Since there are three possible binary states for each permissions
class, the permission for a class of user can be represented as an
octal number. To see a file's permissions use the ls command with the -l option:
ls -l file_name
The first column of information shows that this file has the
permissions set to binary 111101101 which is octal 755 and this gives
the owner read, write and execute permissions, the user's group has
read and execute permissions and everyone else read and execute
permissions. This is the normal permissions setting for a shell script
file.
Pretty boring stuff but you really do need to understand how it works.
There's a setting that usually gives all new files a default
permissions setting. This is umask command:
umask 022
What this means is that all new files will be set to the "mask" of the
this number. A mask in this sense means that every zero will create a
one in the permissions and every 1 will create a zero in the
permissions. Confusing? Of course but here's what's happening:
All Ones
111
111
111
Mask
000
010
010
Permissions
111
101
101
This uses binary addition which I won't go into here but it works
(trust me) and Linux assumes a umask of 022 for all new files you
create. This is usually what you want. All new files you create will
also automatically belong to you and the group you belong to is also
determined by Linux so you don't have to think about that at least.
So now you know all about file permissions and file ownership. You now
need to create a shell script. This is the most interesting and
challenging use of the Linux operating system since you can create all
manner of useful programs for yourself. As a Systems Administrator
you absolutely have to know how to create shell scripts, there's no
more effective way to manage the system. While the Graphical User
Interface (GUI) can do most of the systems management chores, there's
far more possible when you work from the command line. Enough said,
let's do it.
vi get_name
Simple script really but it's doing quite a lot. The echo
command will display the following word or string. If the string
contains spaces or tabs use the double quotes ("). It's usually best to
always use the double quotes whether you need them or not. The -e
option tells the echo command to interpret the \c
notation at the end of the string. (this is a special character that
affects how echo displays the string, see man echo ). The string is a prompt asking for user input.
Next is the read command. This will take
everything you type up to hitting the Enter key and store it in a
variable. The variable here is named, name. It is quoted because we
want to catch the possibility that user enters nothing (just hits
Enter). By using the quotes we can tell if the variable, name, is null
or unset. The difference is that null means the variable exists but has
no value. An unset variable doesn't even exist.
The if statement will compare (test, see man test )
the variable name with null. By using the quotes around the variable,
we can see if it's null or unset. The null value is just the two double
quotes within nothing in between. Without these quotes, the if
statement will fail if the variable is empty because the variable is
unset and therefore can't be tested. With the quotes we can see that
the variable exists but is empty. If the shell tries to test an unset
variable it's going to fail so use the quotes.
If it turns out that the variable is null (you didn't enter anything),
the script will echo a string of text and then exit. A shell script
always have an exit value to let you know if the script completed
without errors. An exit value of zero means that the script has no
errors. There's no benefit to returning a failure exit code because the
script worked correctly even though the user misused it. In other words
the script is ok.
If the user entered something the script will assume that it's his (or
her) name and pass the value of the name variable to the next step.
When the shell sees the fi
it knows that the if statement has completed and move to the next line.
The next line in this case will create another variable named, f1 .
Since the name variable has a usable value (presumably a name), we can
use that value to define the f1 variable. Here we use a variable type
called, command substitution .
This type of variable will have the value of a command we execute. The
command will output something and that is what will become the value of
the variable we want to define.
We use the echo command again to display the value of the name variable we acquired earlier from the read command. This time though we don't display it to the screen, we send it to a "pipe" instead. A pipe
(|) is a mechanism to take the output of a command and dump it into the
input of another command. Think of it as an actual pipe with one end
connected to one command and the other end to some other command. A
simple concept that is hard to explain, just use it to see how it
works.
The cut command that follows the pipe will take the value of the name variable and process it using the -c option. The cut
command is used to cut up a string and display the results. The -c
option means to cut some number of characters. Here we just care about
the first character of the name variable. We take this character and
pass it to another pipe and from there to the tr
command. the tr command will "translate" the character passed to it to
something else. We use it here to convert any lower case letter to
upper case. We capitalize it.
On the next line we do pretty much the same thing except we take all
the characters of the name variable except the first and we don't care
about capitalization.
Next we combine the two variables we just created to create a new value
for the name variable. Now we take this new name variable and echo it
back to the user. He (or she) will see their name displayed and
properly capitalized in case they neglected to do it.
Not terribly exciting but it demonstrates some of the cool things you
can do with a shell script. With just the few commands we used above,
you can device some pretty sophisticated scripts that can give the
appearance of intelligence and choice.
For more detail on these commands use the on-line manual for the commands. Type man and then one of:
read
exit
cut
tr
echo
test
To find about more about variables, man bash . The manual entry for bash
has all manner of detail about creating scripts. While the prose is
difficult and terse, there's most of what you need to know about
creating scripts hidden in its pages. Read it and then read again and
then go back and read it some more. It is the authoritative source of
almost everything you need to know.
You can create little shell scripts to view log files and collect other
information that can make maintaining a Linux system easier. These
kinds of scripts don't have to be very elaborate and, in some cases,
can be replaced with an alias or shell function. Just for practice
though we'll create some scripts to show some of the techniques
available.
vi chklogs
Hit the Esc key to get out of the editing mode and then:
: wq!
This script will expect you to enter the log file you want to view. The
"$1" variable means the first argument after the command (the shell
script name). if you don't provide a log file to view, the script will
assume that you want to view the system log at /var/log/messages . If
you do provide a log file on the command line, the script will use that
file name if it really exists. In both cases the script will use the
log file name you provide or the default to create the variable log .
All of this was done using an if statement. The if
statement will first check (test) to see if there is an argument to the
command. There are several ways to indicate a test condition. I always
use the square brackets ([]) since, for me, it's easier to read. The
test will compare the positional parameter variable $1
to null. If true ($1 is null, notice the double quotes!), then the
variable log is assigned a default value (/var/log/messages). If false
then $1 has a value and execution drops down to the else part of the if
statement. Here we test to see if the file exists (-f). If so we assign
the log variable the value of $1 since we know we have a real log file
name.
Next we use the log variable as an argument to the more
command which will display the file named by the log variable one
screen at a time. The logic of the script is quite simple but preparing
everything is somewhat involved. All we really wanted to do was view a
file but we had to make sure the user entered something we can use. To
ensure that the script will work we have to test the user input before
using it. Lots of scripts have to do this checking to prevent confusing
errors.
After writing and quitting vi we use the chmod
command to change the permissions of the script to make it executable.
Now we can just type the name of the script and provide a log file to
view (or use the default /var/log/messages file):
chklogs
or
chklogs maillog
Let's create little script to monitor the system login information
files for changes. If someone hacks into the machine and modifies these
files by adding a login, we can devise a test to alert us.
All user accounts are stored in the /etc/passwd file. This file has all
the information about a user needed to permit him or her to login. In
most systems the password information is stored in another file,
/etc/shadow that can only be viewed by root
(the system owner and manager, a very powerful special account). The
/etc/shadow file contains the passwords for every user in encrypted
form. While the encryption is pretty much impossible to crack, keeping
even the encrypted form hidden makes it even more difficult to hack
into a user's account.
vi chkpw
Hit Esc to quit editing mode
:wq!
The first time this script is run the root user will
get an email saying the password and shadow files have changed. That's
because the stuff we're checking for doesn't exist yet. You can ignore
this email.
What this script is doing is testing the output of a command and
comparing that to the output of another command. This is accomplished
using command substitution
variables. This kind of variables uses the "grave accent" character (`)
to enclose the command. This kind of quote character tells the shell to
execute the command it contains.
The first command is sum . This command will
do a "checksum" calculation on a file (or string). This will output a
pair of numbers that will be unique for the file. It's very difficult
to change a file without also changing its check sum so it's a handy
way to see if a file has been modified. We are testing the checksum on
the /etc/passwd file.
This is followed by a pipe which passes the output of the sum command to another command, awk . The awk
command is a very powerful command and almost a programming language in
itself (see my awk guide Here). What we want here is to grab just the first two "words"
(fields) of the awk output. The sum command will output three fields (words). The last field is the file name being checked. We don't care about that so we have awk just display the first two, numeric fields. The awk command understands positional parameters
so you can use them the same way as in a regular script: $1, $2, $3,
etc. Since we only care about the first two fields (positional
parameters $1 and $2) we tell awk to only display those two using the built-in awk print statement.
The test operator != says, "is not equal to" (the bang
(!) means "not") so we are comparing the output of the first command
substitution to the output of the next command substitution.
This second command substitution is the output we get with, cat /etc/p.sum .
The cat command will just dump the contents of a
file. When compared we expect both commands to output exactly the same
two numeric fields; the output of both commands should be identical. If
they are not the same we use the mail command to send the root user an alert message.. The -s option to mail
lets us create a subject line for the email. We use the < operator
to pass to the mail command the contents of a file. This < operator
is called "input re-direction" and tells the shell to use this file for
input to the command instead of the keyboard. There is also an output
re-direction operator that sends the output of a file or command to
another file.
The very same logic is used to run the very same tests on the /etc/shadow file. If either test fails, root gets email with an alert message. After all this we use the sum
command to replace the current contents of the two check file with new
checksums. This has the effect of updating these check files for future
checks. After these files are updated, we ensure that they can only be
read or written by root and no one else by using the chmod command.
All we need now is to create the alert file that is mailed to root:
vi pw_alert
Hit the Esc key
:wq!
Now we have a way to track changes to user account information and any attempt to create a new account.
About Quoting
The shell uses different kinds of quoting for different purposes. These quotes are:
Grave accent
`
command substitution
single quote
'
strip any "special" meanings from a string
double quote
"
shell interprets special characters
backslash
\
strip special meaning from the next character
curly brace
{}
enclose a variable to preserve its name
If you use the wrong quote there will be an error or other strange
behavior. When using quotes in a script make sure to provide both an
opening and closing quote of the same type (except for the backslash).
The bash manual entry ( man bash )
has more detail. In almost every case you should use the double quotes
when creating or referring to a variable, "$1" is safer than just $1.
If you need to include a "special character" in a string put the backslash in front of it like this:
echo -e "You owe me \$${100}!"
The backslash in front of the first dollar sign will cause the shell to
display the dollar sign as just another character. The second dollar
sign is not quoted by the backslash so the shell will assume it is a
variable. By enclosing the variable in the "curly braces" ({}), we can
put another character right next to the variable name. Without the
curly braces any character following the variable name will seen by the
shell as part of the variable name and that will most likely not work
as expected.
About "Words" in the shell
The shell chops up the command line into pieces ( arguments ) by using an environment variable called the "Internal Field Separator" or IFS. This will be the space , the tab and the newline
(the Enter key). Because of this behavior, every argument on the
command must be separated from every other by a space or tab. While in DOS or Windows it's ok to type a command like,
dir/w
with Linux something like,
ls-l
will be interpreted by the shell as the single command, ls-l . It is
seen as one "word". These "words" (arguments) are more correctly
called, fields, since many shell commands (like awk )
refer to them as fields in their documentation. It also makes it easier
to visualize a command or string as having fields since quite often you
are creating or modifying files that are flat-file databases where the
notion of records and fields is essential to understanding their
function.
Regular Expressions
One of the handiest features of the Linux shell are "regular
expression". Unfortunately, it's also one of the trickiest to master.
It's worth the trouble to learn what they are and how they are used but
it takes some time. A regular expression is a way to create or find a
string without specifying it explicitly, or sometimes, even knowing
what it is. This is done by substituting a special notation in the
place of the some number of characters. An example would be to take a
string of characters like, "Bill writes excellent documentation for
Linux!" and replace some parts of the string with special characters,
like this:
grep "^[Bb]i.*excel*x$" some_file
Believe it or not this will match the string. The grep
command is used to locate a string in a file. I suggest using the
double quotes (") around the regular expression. If it finds a match it
will display the entire line that contains the match. The regular
expression begins with the caret character (^). This tells grep
to start looking for a string that begins with the following character.
The notation [Bb] will search for a string having either the upper case
or lower case B. So we want a string that begins with either a B or b.
The square brackets ([]) will represent one character only but that
character can be any one of those listed with the brackets. To
represent a range of characters, use this [m-r] or [Aa-Cc].
Following the closing bracket is the letter i with no spaces and then a
dot. This means that the second character in the string will be a lower
case i. the dot (.) represents any character and can be a letter, a
number or even punctuation. Next is the asterisk (*, no space). This
will match anything at all, even nothing. Next comes the letters,
excel. Then another asterisk (matching anything, of any length). Now
comes the letter x and, finally, a dollar sign ($). The dollar sign
means the end of the line. Put it all together and you can match the
example string exactly.
Of course this formula can match lots of other strings too. To ensure
that you only get the string you really want, construct the regular
expression using some unique combination of characters.
You can use a regular expression almost anywhere. With the ls command, for instance, you can match files having some unique part of the file's name:
ls -l *gz
You will see lots of regular expressions used in the various system
configuration files so you will definitely need to understand them to
manage these files. The best source of detailed information is in the
manual entry for ed ( man ed )
which, alas, is difficult to read and understand but the authority on
regular expressions. While ed is one of the oldest UNIX editors, and
rarely used for interactive editing, it is extremely handy within a
shell script.
vi ed_script
chmod 755 ed_script
In this script we're going to use the while statement. The while
statement will evaluate the stuff within the square brackets and, if
the evaluation (test) is true it will drop down to line after the do statement. The test is to see if the $name variable is null. If so (or if it's unset) the script execution will display the echo
line. The first time the script its executed the $name variable won't
be set so the echo statement will execute. This prompts the user to
enter something. If this step assigns something to the $name variable,
then the while statement is satisfied and sends the shell to the line following the done statement. If the user just hits the Enter key, the $name variable will still have no value so the continue statement forces the shell to go back and start over at the while statement line.
Once we've gotten some user input, we cause the shell to use the if statement to perform another test. This time we use grep to find a string in the /etc/passwd file. The -c option to grep
means to just return the count of lines that match. If there is at
least one line matching (the -ge operator in the test means, "greater
than or equal to") then we know we have a string to work on.
Now that we have our matching string, we use the ed command to edit the /etc/passwd file. The notation < here
document. This kind of operation will execute the command that called
it as if was executed from the command line. The << part creates
the here document and the bang (!, or some other
character if you like) tells the shell that everything up the line
containing only a bang (!) is to be executed. When the shell script
sees the bang character on a line by itself, it knows that it has
reached the end of the here document. You can learn more about the here document in the manual entry for bash ( man bash ).
The line:
/^${name}: /
is the same as in the vi editor. The slash (/) characters enclose a regular expression. If the regular expression matches a string in the file that ed is editing, ed jumps to the line having that regular expression. Once at that line, we can give ed some commands that affects just that line.
The next line:
s/:\/bin\/sh/\/bin\/bash
is again like vi. We are telling the ed editor to
substitute a string that begins with the colon character (:). The
notation \/ is how we use the backslash to quote the next character
(quoting with the backslash (\) removes any special meaning from the
following character. This is also known as "escaping" a character's
special meaning). So what we are saying is, "substitute a string that
begins with the colon (:) followed by the slash character (/), the word
bin and then another slash character, and then the word sh with the string, "/ bin/bash
". Pay attention to the "escaped" slash characters. Four of them are
escaped with the backslash and two are not. The two that are not
escaped are used to replace the first string with the second.
Once we've done all that, we send the ed command a w command and then q
command. This will write the changes to the file and then quit. After
that is the bang character (!) that ends the here document. The here document is very handy but it's probably the only time you will use the ed editor.
There's one more script we should try. Suppose we have directory of
files that we want to change the permissions and ownership on.
Ordinarily we would have to run the chmod and chown command on each
file and directory and that could take quite while. Let's use a script:
vi fix_files
Hit the Esc key and then
:wq!
This time we will use the for statement to create the script. The for statement will use a list of things to look at which in this case is the output of the command substitution for the ls command. The for statement will take each line passed to it by ls and put it in the variable we've named " i ". it will then jump to the line after the do statement and execute the lines it finds there. What we're doing this time is using echo to display a informative string to the user. It will also display the current value of the $i variable.
After that the script will use the chmod command to change the permissions for the file named by the current value of $i. Next it executes the chown command to change the file's ownership and group still using the current value of $i. When the shell sees the done
statement it goes back to the top and gets the next line from the list
and performs the same operations on it. When the list has displayed
everything, it's next value will be null and the for statement just quits.
These examples are just some ideas on how the shell can used to create
some really useful scripts. Obviously all the techniques I've
demonstrated can be combined into much more complex and comprehensive
scripts. If you're clever, you can make the machine appear almost
intelligent. When you understand the various capabilities of the shell,
you can read and fully comprehend the system configuration files. By
modifying the system shell scripts, you can add features, enable and
disable stuff and customize things to suit yourself.
If you find that you are frequently typing the same commands over and
over again, consider creating a script (or alias) to automate the task.
A good candidate might be something like:
find . /depth -print |awk '{print $3}'|sed "s/\.tar$/\.tar_file/"
This command is a pain to type and prone to typing mistakes. A shell
script can perform the same function plus have lots of extra features
making the command even more powerful. The easiest way to being is to
just create very simple scripts and add features. Test the script,
bash -x script_name
This will display each line of the script as it is executed and show
the processing of all tests and the assignment of all variables. You
can use the output to find out where the script failed or why something
like a variable wasn't set or had the wrong value.
Systems Administration
The main function of a Systems Administrator is to make sure that the
machine he or she manages behaves like it's supposed to. While it might
seem that setting things up right in the first place would be enough
but it rarely is. Once things are working, the Systems Administrator
has to also monitor everything to make sure it keeps working. It often
happens that a configuration will have to change as features are added
or changed or when something begins to fail or behave erratically.
One of the most common causes for a configuration change is that the
original purpose for having the machine in the first place, changes.
You may have planned on it having it perform some set of tasks and then
decided to add some functionality. There may also be a need to enhance
its performance or enable additional security. The point is that the
way a computer is used can evolve so you have to know manage the
changes.
A second function of a Systems Administrator has to do with the fact
that a Linux machine is meant to be networked to other computers. Most
of the Linux operating system assumes it will have a role in a network
To use Linux for a stand-alone home PC is to waste much of its
capability. Linux is a networked operating system by design.
Almost every administration task on Linux can be done using a GUI
(Graphical User Interface). The default login session will start the
GUI and setup a standard windowing display with icons and mouse
support. The main system menu will contain sub-menus you can access to
manage almost everything. This makes it pretty easy to manage the
system and it's possible that you could do everything using this
interface. Even so, if don't know how to read, modify and create shell
scripts, you will eventually run into some very confusing problems. Use
the GUI for simplicity but be prepared to verify any changes by
examining the files and scripts that are created or modified.
Because you will use Linux in a network, it will help to understand
what that means. A network is supposed to allow computers to exchange
resources. A resource can be a file or printer or information. In a
Linux network a resource can also be a "server". A server is a program
that provides a service to other (client) computers. Linux supports all
the major servers like email, the web, ftp, DNS, DHCP, telnet and a
bunch of others.
The client will connect to the Linux machine (usually called the server because it provides the service you want to access) and request a service.
The Linux machine will start a server program (usually a daemon ) to handle the request. The services use a set of standards called protocols to handle requests. these protocols are very precisely defined and well documented (most often by an RFC , R equest F or C omment). The most common protocol for most services is TCP/IP
(Transmission Control Protocol / Internet Protocol). TCP/IP provides
the connection information for networked computers. Within this
information will be a request for a specific application protocol like ftp or httpd . The TCP/IP and application protocol information is contained in a packet . The packet will also contain the data the application is supposed to process.
The file /etc/services lists all the most common protocols. The file also specifies which port
the application will use. A port in this case is a location that
specifies how the application protocol will communicate with the
application program (daemon). The combination of the requesting
computer's IP address and the port number is called a socket . If a computer wants to telnet
to the Linux server, for instance, it will send a TCP/IP protocol
request packet requesting a connection to the telnet port (23). If the
Linux server accepts the request it passes it to the telnet daemon
(usually /sbin/in.telnetd) and that program will process the request
according to the telnet protocol (as defined in an RFC).
Most of the common daemons are located in either /etc/xinetd.d or /etc/init.d . The xinetd.d files are actually setup files that provide arguments to the daemon to be started. The files in init.d
are shell scripts that execute to provide the daemon's environment.
There are also files in the /etc directory that provide startup
configuration for various other applications (not necessarily daemons).
These files end with the string, .conf and are arguments to the application.
There are some servers and applications that are installed in other places. The webserver daemon, httpd
, is located at /etc/httpd/bin/httpd with its configuration file in
/etc/httpd/conf . The ftp server may be located in a directory named
after the daemon's name like /etc/vsftpd . Almost all of the
configuration files will be somewhere in the /etc directory but they
might also be in /opt or /usr/local . Since they are started by scripts
in /etc/init.d or configuration files in /etc/xinetd.d directories, you
can view these files to find out where the daemon and configuration
files are located. Another good reason to understand shell scripting.
There are also lots of configuration files in the directories named
rc*.d The * will be number from 0 to 6. These numbers represent the
"run-level" to which the system was booted (run-level 5 is the
default). These files are actually links to the files in /etc/init.d . These links will execute a script in /etc/init.d .
Most of the system logs will be in the /var/log directory although some (like httpd )
will keep their logs elsewhere. You can view these logs to find out how
things are working or why they failed. Most log files have the same
format.
The date and time of the entry and which user or which program was
running and any additional information or error messages that the
program output, one entry per line. These logs can provide all the
information you will need to get a good start on locating and
correcting any failures. Some handy network commands for managing the
system are:
netstat
reports what the network cards are seeing
ifconfig
shows the configuration for the network cards
chkconfig
shows or enables/disables network services
route
show the routing configuration
traceroute
see how packets get to another computer
ping
see if another computer is "up"
nslookup
discover a computer's name or IP address
There are also quite a few very handy add-on programs for managing and monitoring the network:
webmin
This provides a great web interface to manage most of the system
nmap
This is part of Linux but it has options you can add. For scanning ports
nessus
a nice graphical port scanner
snort
a packet sniffer to see how your ports are being accessed. Also a good IDS
tripwire
monitors system files to detect changes
mrtg
use to create web based graphs of network traffic usage
When you decide to add a program (package) to Linux you first download
it (try rpmfind.org). You will usually end up with a file having a name
that ends: .tar.gz . The gz part means it's compressed (zipped) and the tar part means that it's an archive. The steps to install the file are usually:
tar -zxvf some_file.tar
This will unpack the archive and install it. There is also usually a
README file and a INSTALL file. Read these to see if you need to do
anything else. The configure shell script will also have information that may make the installation easier.
There are also packages that have been configured to install themselves. Redhat Linux use the rpm (Redhat Package Management) command to install a package:
rpm -i some_file.rpm
Debian uses a command called, aptget to do the same thing.
Once a package is installed it becomes part of the system. You should
check the log files after a new installation to make sure it isn't
causing problems. An RPM usually installs itself in the /usr/local/
directory.
The best way to become a competent Systems Administrator is to
constantly watch the logs and install monitoring software like tripwire
to make sure there are no changes that you haven't authorized. If you
are administering a network server be very careful about what daemons
are enabled and who has access to what. A good place to start is by
creating an /etc/hosts.allow file. This will invoke tcpwrappers
to allow or deny access based on hostname or IP address. Make sure that
every user account has a valid password and pay attention to how users
are using their accounts by checking the logs.
You'll also have to spend a lot of time digging through the on-line
manual. The entries are difficult to read and even more difficult to
comprehend but, once you've done it a few times it gets easier. Linux
also provides a utility for a quick summary of a command:
info cat
There's also hundreds of very handy web sites where you can refer to
case studies and special or interesting uses. Web searches can also
turn up some specific answers especially for unusual log file entries.
Cut and paste a log file error into a Web search and see what happens
(use double quotes to make the whole string one single search term.
Use vi or more to view the various configuration files and server
startup scripts to see how they are constructed. You will learn how
shell scripts are written as well as discover how the system is set up.
Poke around and look at everything. Don't change anything though, just
look and learn. Write simple shell scripts and, once they're working,
add features and try stuff out. If a script fails it will usually
display an error message that you can use to correct problems.
Copy and existing shell script to your HOME directory and play with it.
change little pieces and see what happens. Copy the /etc/passwd file to
your HOME directory and practice finding information using commands
like grep and awk, ed, sed and here
documents. The /etc/passwd file is cool because each item of specific
information is separated by a colon (:) from every other item. You can,
therefore, extract stuff by keying on the colon character. Experiment,
play and learn. You will be surprised how quickly you begin making
sense of it all.
|