2004.12_Gaining Control-a Useful Script for Monitoring Web Servers.pdf
(
5681 KB
)
Pobierz
Layout 1
COVER STORY
Bash scripting
Gaining Control
For some it is just the command line,
but for others it is a full-fledged pro-
gramming language. Bash can be as
simple or as sophisticated as you
want it to be. We’ll show you a great
Bash script for checking up on your
web server, and you’ll meet with
many useful tips along the way.
BY PEER HEINLEIN
between a user and the operating
system kernel. The shell performs
simple tasks and derives its name from
the fact that it surrounds the kernel just
like a seashell protects its inhabitant. But
it wasn’t long until shells started to get
smart, and now most shells have power-
ful features that almost put them on a
par with full-fledged programming lan-
guages. Bash, the Bourne Again Shell, is
the most popular of Unix shells at pre-
sent, and has easily outpaced its
predecessor, the Bourne Shell, and deriv-
atives such as the C shell, the TC shell or
the Korn shell.
Shell scripts cannot be compiled, and
this can affect their speed of execution.
On the other hand, experienced admins
can put together a shell script in no time
at all; shell scripts are easily readable,
and if the programmer uses the options
the shell provides, a script really is capa-
ble of solving complex problems.
A shell script is basically a series of
commands that a user could enter at the
command line prompt. In other words,
any commands you enter manually
could be scripted with just a few lines of
shell script. With a minimum of effort,
admins can write scripts to automate
recurring jobs, using cron to run the
script or running it automatically at login
time. These scripts could manage back-
ups, statistical analyses, or even
availability checks.
The trick with shell programming is to
put small building blocks together in as
efficient a way as possible. As this article
will show, you can build very sophisti-
Keep It Simple
When you are trying to achieve a specific
result with shell programming, the lack of
options or functions is not really the issue.
This said, it is often difficult to identify a sim-
ple approach. Many administrators are used
to performing recurring tasks manually in
the shell, but they refuse to script the exact
same steps and instead go through all kinds
of contortions to find a solution.
It is easy to check the number of user
accounts with user ID
0
in
/etc/passwd
: just
open
/etc/passwd
, search for zeros, and
count. But what if you want to script that?
In fact, there is no need to change anything:
just
grep :0: /etc/passwd
to filter any
accounts with user or group ID 0 from the
file, and use
wc -l
to count them. A simple
task, but even experienced admins can end
up with complicated approaches. To avoid
this, it makes sense to divide any administra-
tive work you want to script into smaller
steps. This makes it easier to identify the
right tools for the job.
Don’t start off by launching your favorite
editor to enter the script; instead try out all
the commands one by one in a terminal win-
dow, and check the output. If these manual
steps lead to the solution you need, you have
a script module that is worth “saving for pos-
terity” in a file.
Of course you are not restricted to the built
in bash commands. On the contrary, the real
strength of the shell is the amazing variety
of popular public domain tools.
20
December 2004
www.linux-magazine.com
Building a Bash web admin script
A
shell is simply an interface
Bash scripting
COVER STORY
cated and useful Bash scripts from small
blocks of code dedicated to specific
tasks.
Variables – the $ Sign in a Different Light
It is probably safe to assume that most read-
ers know how to use the bash shell
interactively. But commands that hardly ever
occur in interactive mode – variables, loops,
and control structures – may be a different
thing altogether.
Variables should be capitalized for the sake
of readability; they do not need to be typi-
fied (integer, string or the like). To assign a
value to a variable, leave out the dollar sign:
USER="Tux"
But if you want bash to replace a variable
with its current value, you need to use the
dollar sign prefix:
echo "Hallo $USER"
Variables are only visible within the current
shell. If you launch a sub-shell, the variables
you have been using will not be visible,
unless you have exported them explicitly to
create global variables:
USER="Tux"
export USER
You can combine these steps:
export USER=Tux
Variables also support simple math. You
need to place the mathematical operation in
brackets
$[ ... ]
. Make sure you insert space
characters to separate the variable from the
brackets:
NEW = $[ $OLD + OLD * 2 ]
Variables can occur in a text string. For
example, the following call
echo "Hallo $USER-User"
would output “Hallo Tux-User” in our exam-
ple. Variables that start with the same
letters, such as
$USER
and
$USE
could lead to
some confusion; it makes sense to put the
variable names in curly brackets to avoid
this:
echo "Hallo ${USER}-User"
A Web Server Administration
Script
Suppose you perform a series of web
server checks on a regular basis and you
would like to automate the tasks using a
Bash script. You would, perhaps, come
up with a script similar to the script
shown in Listing 1. As you can see, the
script consists of several different blocks
of code dedicated to different web server
administration tasks. You’ll learn about
the steps of the server check in the fol-
lowing sections.
The script in Listing 1 begins with the
definition of the interpreter. If this defini-
tion is missing, the default shell of the
user executing the script would attempt
to run the script commands. Today’s
Linux distros typically use
/bin/bash
as
the default shell, but an explicit defini-
tion at this point doesn’t hurt, and it can
help avoid potential errors.
You may have also noticed something
that
isn’t
referenced at the beginning of
the script: a config file. For simple
scripts, it is not worth creating a script
config file. If the parameters were more
complex, however, it might make sense
to create a special file below
/etc
; the
main script could then parse
. /etc/server
check.conf
– note that the dot and the
“The power of Dedicated Hosting, at the price of Shared.”
Let’s face it – if you’re building and testing your own web-based applications, designing & hosting your clients’ websites, or just own
a very busy site – what you really want is your own server. But sometimes the cost of running a dedicated environment is just too
prohibitive.
So wouldn’t it be great if you could share the cost of the server but not share the resources?
In other words, the full power of your own server - in a shared environment.
Hostway’s new VPS solution has a proprietary partitioning system that allows multiple server set-ups on the same box, with the guaran-
teed CPU, Disk Space and Network resources that you wouldn’t get in a normal Shared Environment.
Together with full root or control panel access, choice of open source software at install, IP- table fi rewall, 24hr Roll-Back backup option
and Hostway’s steadfast commitment to customer care, it adds up to a pretty unique solution.
Hostway
– Hosting the way
you
want it.
call us now on
0808 180 1880
• sales@hostway.co.uk •
www.hostway.co.uk/
virtual
Domain Registration • Web Hosting • Resellers • E-commerce • VPS • Dedicated Servers | Australia • Canada • Germany • Korea • Netherlands • United Kingdom • United States
COVER STORY
Bash scripting
path are separated by space characters.
This would even allow you to support
“includes” just like the ones used by
other programming languages, providing
some degree of modularity for more
complex programs. A file referenced in
this way would be inserted into the exe-
cution path and executed.
of the expression within the quotes, and
inserting the output instead of the com-
mand – a kind of cut & paste. There are
three different kinds of quotes, but the
shell will only accept one of them as the
command substitution character. What
we need is a so-called back tick.
The command uses
date
to obtain the
current date. The
date
manpage is
unclear in parts, and you need some
bash programming experience to read it
correctly. The Synopsis area of
man date
shows a call to
date +FORMAT
, and the
manpage later goes on to explain the val-
ues that
FORMAT
can have. It is easy to
overlook the fact that you need to keep
the
+
parameter, as you are only substi-
tuting
FORMAT
. In other words, you
need the following syntax to substitute a
date:
date +%Y%M%D
.
The second problem is the blank in the
date output format, as in
AUG 25
, which
is often seen in logfiles.
date +%d %e
will cause an error, as will
date +%d
+%e
. You also need to enclose the for-
mat block in quotes or ticks. This
indicates that the space character does
not mark the point where the next
date
parameter starts:
date +"%d %e"
or
date +'%d %e'
– but of course you can-
not use back ticks here, as they are
reserved for command substitution.
The Heading
Before we start recording information on
the status of the server, it is a good idea
to print a heading giving the host name
and the date of the check. This heading
information is generated using the fol-
lowing lines:
Is Your Server Running?
The first check the script will perform is
to determine if the web server is run-
ning. The code that performs this check
is as follows:
DATUM=`date +'%d %e'`
echo Subject: Server-Status
U
`date +"%b %e"` $HOSTNAME
01 # Check if web server is
running
02 # Customized for Apache2, use
"/etc/init.d/apache"
03 # and "/usr/sbin/httpd -T"
otherwise.
04 if [$CHECK_WEB = "yes" ] ;
This first line uses the technique of com-
mand substitution, executing the whole
Listing 1: servercheck
001 #!/bin/bash
002 #
003 # Sample script for
monitoring a httpd server
004 #
005 # Heinlein Professional Linux
Support GmbH, 8/04
006 #
http://www.heinlein-support.d
e
007 #
008
009 # Generate secure tmp file
for output
010 umask 077
011 TEMPFILE=`mktemp /tmp/serverc
heck.tmp.XXXXXXXX`
012 # Minimum space for "/" in
percent
013 HDMINFREE="90"
014
015 # To-do list
016 CHECK_WEB=yes
017 CHECK_ACCOUNTS=yes
018 CHECK_HDMINFREE=yes
019 CHECK_LOGINS=yes
020 CHECK_STATUS=yes
021
022 #
023 # No config changes from this
point on.
024 #
025
026 DATUM=`date +'%d %e'`
027
028 echo Subject: Server-Status
`date +"%b %e"` $HOSTNAME
029 echo
030 echo
031
032 # Check if web server is
running
033 # Customized for Apache2, use
"/etc/init.d/apache"
034 # and "/usr/sbin/httpd -T"
otherwise.
035 if [ $CHECK_WEB = "yes" ] ;
then
036 if /etc/init.d/apache2 status
&> /dev/null && wget
--delete-after
http://www.domain.local/check
file.txt &>/dev/null ; then
039
/etc/init.d/
apache2 reload &>/dev/null &&
echo " Web server running
and config reload okay."
040
else
041
echo "###
WARNUNG: Reload failed due to
CFG error! "
042
fi
043 else
044
# Web server not
running! Try to launch!
045
if /usr/sbin/httpd2
-t &>/dev/null && /etc/init.
d/apache2 start &>/dev/null ;
then
046
echo "###
WARNING: Web server was down,
restart successful."
047
else
048
echo "###
WARNING: Web server was down,
restart FAILED! "
049
fi
037
# Web server is
running! Try reload, perform
syntax check before doing so
050 fi
051 fi
052
053 # Check /etc/passwd for
hidden root users
038
if /usr/sbin/httpd2
-t &>/dev/null; then
22
December 2004
www.linux-magazine.com
Bash scripting
COVER STORY
then
05 if /etc/init.d/apache2 status
&> /dev/null && wget --delete-
after http://www.domain.
local/ checkfile.txt &>/dev/
null ; then # Web server
is running! Try reload,
perform syntax check before
doing so
running! Try to launch!
return value of the program. The return
code or
errorlevel
will be
0
for a program
that completes correctly; this is equiva-
lent to
TRUE
in the shell’s binary logic,
whereas any error will return a code
with a value other than zero, and thus
the binary equivalent of
FALSE
.
As the
if
condition simply checks for
true/false statements, you can substitute
the command here:
if /etc/init.d/apache
status ; then...
. Exactly the same
approach is used just two lines down.
The
httpd
, also known as Apache, has a
-T
option for checking the configuration
– again the return value can be true (if
the configuration is okay) or false (if a
syntax error occurs). This test is particu-
larly useful as it avoids killing a running
web server by attempting to reload after
inadvertently adding a fatal error to the
web server configuration.
The script does not entirely rely on
/etc/init.d/apache status
to check the
13
if /usr/sbin/httpd2 -t
&>/dev/null && /etc/
init.d/apache2 start
&>/dev/null ;then
14
echo "### WARNING:
Web server was down,
restart successful."
15
else
06
if /usr/sbin/httpd2 -t
&>/dev/null; then
16
echo "### WARNING:Web
server was down,
restart FAILED! "
07
/etc/init.d/apache2
reload &>/dev/null
&& echo " Web server
running and config
reload okay."
17
fi
18 fi
19 fi
08
else
The second
if
condition is as an example
of the elegant programming style the
shell supports. The start/stop script
/etc/init.d/apache
has an option for
checking if the Apache daemon is run-
ning. Instead of interpreting the text
output from this command, we’ll use the
09
echo "### WARNUNG:
Reload failed due to
CFG error! "
10
fi
11 else
12
# Web server not
Listing 1: servercheck
054 if [ $CHECK_ACCOUNTS = "yes"
];then
055 cat /etc/passwd | grep ":0:"
|grep-v^root: > $TEMPFILE
056 ACCOUNTS=`cat $TEMPFILE | wc
-l`
057 if [ $ACCOUNTS -ge 1];then
058
echo "### WARNING:
Discovered $ACCOUNTS
additional accounts with root
privileges!"
$KDISFREE% / INODEISFREE% of
root partition occupied! "
071 else
072 echo " Hard disk space
for root partition okay."
073 fi
074 fi
075
076 # Check for failed logins
077 # Modify grep pattern to
reflect your own log format
if needed.
078 if [ $CHECK_LOGINS = "yes" ]
; then
079 cat /var/log/messages | grep
"$DATUM" | grep -i "FAILED "
|grep-i"root" | grep -v
"tty" |> $TEMPFILE
080 FAILLOGINCOUNT=`cat $TEMPFILE
|wc-l`
081 if [$FAILLOGINCOUNT -ge 15 ]
; then
082 echo "### WARNING:
More than 15 failed root
logins! "
083 elif [ $FAILLOGINCOUNT -ge 1
];then
logins:"
085 fi
086 cat $TEMPFILE
087 fi
088
089 # Generate status:
090 if [ $CHECK_STATUS = "yes" ]
; then
091 echo
092 echo "General server status:"
093 echo
"-----------------------"
094 echo
095 echo "Current load in last 15
minutes: `cat /proc/loadavg |
sed "s/.* .* \(.*\) .*
.*/\1/"`"
096 echo
097 echo "Memory usage:"
098 cat /proc/meminfo | head -n 3
099 echo
100 echo "The following users are
currently logged on:"
101 who
102 fi
103 echo
104 echo
105 rm $TEMPFILE
059
cat $TEMPFILE
060 else
061 echo " No
additional root accounts."
062 fi
063 fi
064
065 # Check for HDMINFREE
066 if [ $CHECK_HDMINFREE = "yes"
];then
067 KBISFREE=`df | grep /$ | cut
-b 52-54`
068 INODEISFREE=`df -i | grep /$
| cut -b 47-49`
069 if [ $KBISFREE -ge $HDMINFREE
-o $INODEISFREE -ge
$HDMINFREE ] ; then
084
echo " Discovered
following failed root
070
echo "### WARNING:
www.linux-magazine.com
December 2004
23
COVER STORY
Bash scripting
Listing 2
tem, the script outputs a warning. Other-
wise the script states that no root users
were found.
you are most in the need of accuracy –
that is when the disk is completely full.
The
if
condition in the square brackets
simply contains the abbreviation of a
test
command. If we expand this, we get
if
test $HDISFREE -ge $HDMINFREE ; then
– these notations are equivalent.
test
can
check use variables or files to check for
true/false conditions. In our case
-ge
stands for “greater than or equal”; in
other words, we are checking to see if
the disk space usage for the system is
01 # Check /etc/passwd for hidden
root users
02 if [ $CHECK_ACCOUNTS = "yes" ]
; then
03 cat /etc/passwd | grep ":0:" |
grep -v ^root: > $TEMPFILE
04 ACCOUNTS=`cat $TEMPFILE | wc
-l`
05 if [ $ACCOUNTS -ge 1];then
06 echo "### WARNING:
Discovered $ACCOUNTS
additional accounts with root
privileges!"
07 cat $TEMPFILE
08 else
09 echo " No additional
root accounts."
10 fi
11 fi
Checking Hard Disks for
Minimum Free Space
The next check looks to see whether the
server hard disk has sufficient free
space? This code block in Listing 1,
which begins with the line:
# Check for HDMINFREE
uses the HDMINFREE variable, which is
defined earlier in the script:
Listing 3: Evaluating
Parameters
# Minimum space for "/"
U
in percent
HDMINFREE="90"
01 while [ "$#" -gt 0];do
02 case $1 in
03 --web)
04 CHECK_WEB=yes
05 shift
06 ;;
07 --accounts)
08 CHECK_ACCOUNTS=yes
09 shift
10 ;;
11 --hdminfree)
12 CHECK_HDMINFREE=yes
13 shift
14 ;;
15 --status)
16 CHECK_STATUS=yes
17 shift
18 ;;
19 --logins)
20 CHECK_LOGINS=yes
21 shift
22 ;;
23 --all)
24
HDMINFREE defines the minimum free
disk space threshold that will trigger a
warning. Placing this value in a variable
allows you to change the setting more
easily than if the value were hard coded
into the logic of the Bash script.
How do you discover the current level
of disk usage? There are two tools for
this job:
du
gives you the hard disk
usage, and is not very useful within the
confines of our script.
df
shows you the
free space on one or multiple partitions,
but in a fairly verbose way. The best
approach is to do what any human
would do: launch
df
, locate the lines for
the
root
partition, and read the numbers
in front of the percentage signs.
Instead of checking for the partition
name (
hda3
), it is a lot easier to look for
a slash character
/
at the end of a line.
This makes it easier to apply the script to
other configurations. In other words, we
just grep the output from
df
for
/$
, where
$
is the symbol for end of line (EOL).
One alternative might have been to
use
df /
, but
df
would have given us out-
put with column headers, and that
would have meant using
tail -n1
to filter
the line. In other words, we would not
have made things any easier.
cut -b 52-54
and
cut -b s47-49
surgi-
cally remove the percentage, which we
can then store in a variable for later com-
parison in the
if
condition. Watch out for
the pitfalls here: if you cut
53-54
, the
script would just take the two zeros from
100 percent, and that would mean the
script giving you unreliable results when
Apache status. Instead, it uses
wget
to
check if a file download works out;
admittedly this is really just our way of
demonstrating the use of the tool. Again
wget
returns a true/false code which
leads us to the
if true AND true ; then...
expression. If one of these tests does not
check out, the script moves on to the
else branch.
The text output from the commands in
the
if
conditions here is redirected to
/dev/null
. The idea behind this script is
to give us a status report; output from
the programs themselves would only get
in the way of that.
Checking /etc/passwd for
Hidden Root Users
Since you are already checking to see if
the web server is running, you might as
well also check to see if any hidden root
users are currently logged in to the sys-
tem. The code in Listing 2, which is an
excerpt of Listing 1, checks /etc/passwd
for hidden root users.
As you can see, the code in Listing 2
uses a
grep
statement to search the con-
tents of the /etc/passwd file to see if any
users with root status are currently using
the system. Results of successful
searches for root users are accumulated
in ACCOUNTS, and, if ACCOUNTS
reveals one or more entries indicating
that a root user has gotten onto the sys-
CHECK_WEB=yes
25
CHECK_ACCOUNTS=yes
26
CHECK_HDMINFREE=yes
27
CHECK_LOGINS=yes
28
CHECK_STATUS=yes
29
shift
30
;;
31 *)
32
echo "Usage: $0
[--web] [--accounts]
[--hdminfree] [--logins]
[--status] [--all]"
33
exit
34
;;
35 esac
36 done
24
December 2004
www.linux-magazine.com
Plik z chomika:
SOLARIX33
Inne pliki z tego folderu:
2010.10_Popular Demand-Sql Selects in Javascript with Publicsql.pdf
(728 KB)
2010.10_New Start-What's Coming in Html 5.pdf
(645 KB)
2010.10_Hook, Line, and Sinker-Testing Web Applications with Google's Skipfish.pdf
(756 KB)
2010.10_Easy Street-Simplifying Site Management.pdf
(601 KB)
2010.09_Return of the Lost Sibling-Failure Tolerance with Xen 4 and Remus.pdf
(634 KB)
Inne foldery tego chomika:
Ask Klaus
Beginners
Comment
Community
Community Notebook
Zgłoś jeśli
naruszono regulamin