Core admin: sysadmin toolkit



operating system used
various
document history
version date changes
1.0.0 2004-01-01 conceived
1.1.0 2005-01-01 undocumented changes
1.2.0 2006-05-01 - new document history scheme
- added screen utility

preamble

Hi. So here I will attempt to build us a nice sysadmin toolkit. What is that you ask? Let's say it is what your average system administrator should always be walking around with. It contains a slew of commands and utilities that are, in my opinion, indispensable to any sysadmin no matter what his/her area of expertise. This is an ambitious undertaking and I hope visitors will contribute some ideas of their own by emailing me.

I have partitioned this tutorial into three chunks:

  1. standard toolset
  2. custom toolset
  3. networking utilities
  4. miscellaneous
  5. advertisement

The tools looked at will not be receiving a comprehensive treatment by any stretch of the imagination. The reader is urged to plumb the depths of those topics he/she finds interesting.

standard toolset

I will collectively refer to commands/tools usually provided with the base Unix installation as the standard toolset.

Here is a list of what we will see in this section:

  1. cd, cp, mv, mkdir, rm, rmdir, cat, clear, less
  2. df, du, free
  3. file, whatis, man
  4. find
  5. grep
  6. head, tail, wc
  7. locate, which, whereis
  8. ls
  9. ps, top
  10. sed
  11. uname, uptime
  12. w, who, whoami, last

cd, cp, mv, mkdir, rm, rmdir, cat, clear, less

RTFM!

df, du, free

These three utilities deal with space and memory.

df gives you an overview of the manner in which your hard disks are partitioned and how much space is used in each partition.

Typical usage:

$ df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/wd0a     1006M   96.8M    859M    10%    /
/dev/wd1a      183G   32.0G    142G    18%    /home
/dev/wd0d      5.9G    4.8G    826M    86%    /root
/dev/wd0e      5.9G    2.4G    3.2G    43%    /usr
/dev/wd0f      2.0G    187M    1.7G    10%    /tmp
/dev/wd0h     87.9G   31.7G   51.8G    38%    /var
/dev/wd0g     78.7G   32.2M   74.8G     0%    /var/log
	

The du command displays the block system usage (greater than the actual file size) of a specified file or directory. If you specify a directory you will only get statistics on subdirectories. You must have the appropriate permissions to access the statistics.

An example where we want info on usage of a specified directory as well as the summary of the directory itself (the last line):

$ du -h /tmp/bnc
6.0K    /tmp/bnc/help
2.0K    /tmp/bnc/lang
2.0K    /tmp/bnc/log
2.0K    /tmp/bnc/menuconf/help
4.0K    /tmp/bnc/menuconf
2.0K    /tmp/bnc/motd
2.0K    /tmp/bnc/scripts/example
4.0K    /tmp/bnc/scripts
2.0K    /tmp/bnc/src
2.0K    /tmp/bnc/tools
250K    /tmp/bnc

The reason the last line (the directory) and the above lines (the subdirectories) do not add up is because there are some files under the directory that are not considered.

An example where we want system block usage of a directory only:

$ du -sh ~
44.0K   /home/petermatulis

The third command is free. This is a very useful command but it is not native to FreeBSD or OpenBSD. It is a Linux thing. For something comparable, try the FreeBSD port for the muse utility:

$ muse -m

The output (on my smashing new box I might add),
Active:       10.012 MB
Inactive:    243.719 MB
Wired:       114.566 MB
Reserved:      1.617 MB
Cache:         0.000 MB
Kernel:        0.133 MB
Interrupt:     0.008 MB
Buffer:      111.234 MB

Total:       997.223 MB
Free:        628.379 MB

file, whatis, man

The file program attempts to determine the nature of a file (its type). Possible types include:

In addition, the file command recognizes a plethora of well-known formats. It uses the /etc/magic file for this.

Syntax:

$ file some_file

The whatis command will provide a very brief summary of the purpose of a command. Actually, it provides information available in the manual pages.

Syntax:

$ whatis some_command

To get more details on a command, therefore, use the manual pages themselves via the man utility. The manual pages also contain information on non-executable files.

Syntax:

$ man some_file_or_some_command

A useful feature of man is to have it search itself for manual entries matching a keyword:

$ man -k keyword

Example:

$ man -k bash
bash (1) - GNU Bourne-Again SHell
bashbug (1) - report a bug in bash
	

find

The find command is one command you need to have good control over to be an efficient sysadmin. I will give examples of some useful forms.

To find a file with the given pattern, below the /usr directory, owned by the root user, and give a long directory listing of the matches:

# find /usr -type f -name 'a*f*[sf]' -user root -ls

To find a directory with the given pattern below the / directory, owned by group wheel, and apply the du command to the returned matches:

# find / -type d -name 'p*' -group wheel -exec du -sh {} \;

The above could of been done by piping the results to the xargs command:

# find / -type d -name 'p*' -group wheel | xargs du -sh

To find any type of file, below the /home directory, with a size greater than 256 kB, and with permissions 775:

# find /home -size +256000c -perm 775

To find a file below /usr/local, modified within the last 48 hours, but contained within 4 directory levels (/usr/local being the first level):

# find /usr/local -type f -mtime -2 -maxdepth 4

To find a file below the / directory, accessed within the last minute, but contained lower than 1 directory level (/ being the first level):

# find / -type f -amin -1 -mindepth 2

grep

This utility searches files for lines containing a match to a given pattern. I am using grep (GNU grep) 2.4.1 here

To search for the pattern "LaserJet" in the file /etc/magic while ignoring the case of the pattern:

$ grep -i LaserJet /etc/magic

To search for the pattern "LaserJet" in all files in the current directory and give just the number of matches found:

$ grep -c LaserJet *

To search for the whole word "LaserJet" in the file /etc/magic and include the 2 preceeding lines and the 2 succeeding lines:

$ grep -2 -w LaserJet /etc/magic

To search among multiple patterns (one per line) found in the file "grepstrings" in the file /etc/magic. Finding any one pattern will produce a match:

$ grep -f grepstrings /etc/magic

To search for a string containing metacharacters in the file /etc/magic:

$ grep -F ok?*w /etc/magic

To search for the string "LaserJet" in all files in the /etc directory (and its subdirectories) and include line numbers:

$ grep -n -r LaserJet /etc

An inverse search. Only lines not containing the pattern "Laser Jet" in the file /etc/magic:

$ grep -v 'Laser Jet' /etc/magic

GNU grep has powerful regular expression capabilities. Here are a few examples.

Two equivalent ways to search for lines beginning with a digit in the file /etc/magic:

$ grep ^[0-9] /etc/magic $ grep ^[[:digit:]] /etc/magic

To search for 5 characters in the file /etc/magic. The first character is alphanumeric at the beginning of a word, followed by any 2 characters, followed by the digit 4, followed by any character at the ending of the word:

$ grep '\<[[:alnum:]]..4.$' /etc/magic

To search for a word in the file /etc/magic that begins with 7 or more digits in the range of 1 to 9:

$ grep '\<[1-9]\{7,\}' /etc/magic

We can create a situation where one or more expressions finds a match. Below we search for the strings "$5000" and/or "$10000" in the file /etc/magic. Notice how we force grep to act as egrep by employing the '-E' switch. egrep is better suited for regular expressions:

$ grep -E '\$5000|\$10000' /etc/magic

We can also use the output of another command as the input for grep using a pipe:

$ dmesg | grep 'isa\|irq'

Above we're taking the output of the dmesg command and filtering it through to grep. Here, grep searches for any lines containing the strings "isa" and/or "irq". I use this one often when troubleshooting network interfaces and modems.


To specify that a line must contain both isa and irq we pipe into a second grep:

$ dmesg | grep isa | grep irq

locate, which, whereis

These three utilities are used to quickly locate files. Each one is implemented in slightly different ways.

locate searches a database (OpenBSD default is /var/db/locate.database but it can be specified with the "-d" switch) for all pathnames which match the specified pattern. The database is recomputed periodically (usually weekly or daily), and contains the pathnames of all files which are publicly accessible.

The simplified syntax for locate is:

$ locate pattern This will be taken as '*pattern* '

Use locate for files that do not have the executable attribute or for strings found anywhere in the pathname.

For example,
$ locate ml/8

The output,
/usr/local/share/doc/aspell/man-html/8_How.html

which takes a name (or list of names) and returns the absoulte filenames of commands that would be executed had these names been given as commands. This utility depends completely on the PATH environmental variable; if it is not defined then it will fail unless the name is given as a correct relative or absolute pathname. Only the paths found in this variable will be searched so there may well be executables on the filesystem that are not found. Also, only the first match in the PATH is given as output (use the "-a" switch to display all matches).

The simplified syntax for which is:

$ which name(s)

Use which for files that have the executable attribute.

For example,
$ which man ls ps

The output,
/usr/bin/man
/bin/ls
/bin/ps

whereis performs the same task as which. The only difference is in the paths it searches. Whereas which uses the paths found in the PATH variable whereis uses those returned by the sysctl(8) utility for the "user.cs_path" string.

On a random system here are the differences in these paths:

$ sysctl -a user.cs_path
user.cs_path=/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin
$ echo $PATH
/home/petermatulis/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/games:.

ls

A basic but indispensible command. I include it here because it is one of the first commands a new user encounters but then never bothers to learn any of its many useful options.

To show a long listing; show hidden (dot) files but supress the current and parent entries (. and ..); and apply the command to all subdirectories as well:

$ ls -lAR

To show a long listing; show all hidden files; sort by size (largest first); and show size in "human readable" form:

$ ls -laSh

Note: I found the "h" option available only with Red Hat.


To show a long listing; show all hidden files; show the time a file's status was last changed; and express user and group in numerical format:

$ ls -acn

Notice how the "n" option implies a long listing.


To show a long listing; show all hidden files; show the time a file was last accessed; and reverse the sorting order (here it will show latest accessed file last):

$ ls -laur

To show a long listing; show all hidden files; sort by modification time (latest first); and show in detailed time format:

$ ls -latT

Note: Only on OpenBSD does the "T" switch assume the above meaning. On Red Hat, you specify "--full-time".


Determine how many excutables reside in the /usr directory (and its subdirectories):

$ ls -FR /usr | grep $'*' | wc -l

Above, the files that have their executable bit set (by either owner, group, or other) are listed due to the "F" switch where such files are identified by a star (asterisk). The output to this command on my OpenBSD 3.3 system is:

10778

Other types of files are identifiable using the "F" switch. The OpenBSD man page:

-F      Display a slash (`/') immediately after each pathname that is a
             directory, an asterisk (`*') after each that is executable, an at
             sign (`@') after each symbolic link, a percent sign (`%') after
             each whiteout, an equal sign (`=') after each socket, and a ver-
             tical bar (`|') after each that is a FIFO.

ps

sed

Sed is known as a stream editor and is shipped with all Unix variants. Its chief purpose is to edit text files by performing deletions and substitutions. This editing is based on a rule (or rules) specified on the command line or in a file. This makes it a non-interactive editor. This also allows shell scripts to utilize sed to perform repetitive tasks. The input text is read from a file or a pipe (output from another command) and the modified results are sent to standard output or to a file.

Before getting bogged down in details let's look at sed in action:

$ cat file
The fox jumped over the stream.
$ sed -e 's/fox/horse/' file
The horse jumped over the stream.
$ sed -e 'd' file
..............................

What we did there was replace the word "fox" with the word "horse" and the results were automatically sent to standard output (the screen). Then we deleted every line (there is only one) in the file so there is null as output (the last line is a blank line). An important point to note is that the original file remains unchanged. This is a trivial example. The power of sed becomes apparent when either mass editing of files is required or when editing of files (on any scale) is needed at predetermined times.

Sed syntax

There are four ways to invoke sed:

1. sed -e 'command1' -e 'command2' -e 'command3' file
2. {shell command} | sed -e 'command1' -e 'command2'
3. sed -f sedscript.sed file
4. {shell command} | sed -f sedscript.sed
{ sed commands on the command line with input from a file }
{ sed commands on the command line with input from output of another command }
{ sed commands from a file with input from a file }
{ sed commands from a file with input from output of another command }

Input is always processed line by line. So if the input is a file consisting of fifty lines then sed is applied fifty times (with each line being processed independently). And as explained above, the "command" may be a deletion or a substitution. When multiple commands are used each successive command acts upon the result of the preceeding command. The text that sed is currently working on is called the pattern space.

Deletion

The format of the delete command is as follows:

[address1[ , address2 ] ]d

In sed, addresses represent lines. If one address is given, then the command is applied to lines containing that address. An address can be either a regular expression enclosed by forward slashes /regex/ , or a line number . The "$" symbol can be used in place of a line number to denote the last line. If two addresses are given, then the command is applied to all lines between the two lines that match the pattern.

Here we are deleting the first six lines of the file "test":

$ sed -e '1,6d' test

Below we remove all lines ending with the string "taoist.". Notice that I escape the period. I do this to be explicit about the ending period because if I don't do this then "." will act as a regex (any one character):

$ sed -e '/taoist\.$/d' test

We can only delete entire lines using the delete command. In order to delete parts of a line (like a word) you must use the substitution command and use a null character as the replacement.

Substitution

The format of the substitute command is as follows:

[address1[ ,address2]]s/pattern/replacement/[flags]

The pattern (not the pattern space) is some regular expression (or simply a string or word) and the replacement is a string we want to replace the pattern with. sed regular expressions are essentially the same as those used with grep.

The flags can be any of the following:

For some reason we cannot use the "w" option with the delete command. If we want to send the results to a file we need to use redirection:

$ sed -e '/taoist\.$/d' test > test_modified

This next example tells sed to operate on any line in the file "test" contaning the word "peter" and to erase the second instance of the word "This" (via the use of a null character):

$ sed -e '/peter/s/This//2' test

This tells sed to operate on lines 3 through 15 (inclusive) in the file "test" and to replace all instances of the word "This" with the word "That" and send the results to the file "test_modified":

$ sed -e '3,15s/This/That/gw test_modified' test

Let's move on to something more mature. My task is now to perform a mass substitution to all my HTML documents. For instance, I want to change an image that resides on all my pages, say, "email.jpg" to "email.gif". The first thing to notice is that I am now dealing with multiple files whereas before I always dealt with single files. In such a case I need to write a script (call it "replace.sh") that contains a reiteration (a loop):

#! /bin/sh

TMP=/tmp/replace.sh.tmp

find $1 -type f -name "*$2*" | while read i
  do
     cat $i | sed -e "s/$3/$4/g" > $TMP
     mv $TMP $i
  done
    

I am employing four positional variables here. The second form of the sed syntax given earlier is being used. Also notice how I need to use double quotes in order to expand my variables.

Here is how I would invoke the script (assuming it resides in my PATH; that all HTML documents are stored under the /www directory; and that the documents contain the string "html" in their filenames):

$ replace.sh /www html email.jpg email.gif

Caution: Before using a sed command on existing documents ensure you have done enough testing. This is especially true if you are working with multiple files.

More sed information:


custom toolset

I will collectively refer to commands/tools not necessarily provided with the base Unix installation as the custom toolset.

Here is a list of what we will see in this section:

  1. multitail
  2. screen

multitail

screen

GNU Screen is a handy tool for those people who find themselves with many (command line) terminals open simultaneously. It is also valuable if you run commands that a) take a long time to complete and b) produce output that you are interested in monitoring. It is the classic command-line geek tool.

The man page describes it like this:

Screen is a full-screen window manager that multiplexes a physical terminal between several processes (typically interactive shells).

It is also useful as an educative tool since multiple users can attach their login sessions to existing shells. The possibility of remote connections (typically via SSH) amplifies the power of this last feature which should naturally be dampened with the appropriate security measures.

It is invoked very simply:

$ screen

At this point all commands used to control screen itself must be prepended with the default C-a (Ctrl-a) keystroke. Otherwise you can proceed as you normally would on the command line.

Basic usage

Here are some rudimentary commands to get you started. The commands provided below are the defaults for my installation. YMMV.

creating
The first action you will want to take is to create some extra screen windows. This is analogous to tabbed internet browsing. The command to create another window is c (create). Hence:

$ C-a c

selecting
To select a window use n (next) and p (previous). Each window is also assigned a number that can be used instead. A third method is via a menu: ". Yet a fourth, and probably the easiest, way is <SPACE> (the SPACEBAR) which scrolls through the windows in order.

splitting
Another popular feature is to split the current window into two regions (horizontal splitting; one on top of the other). This is accomplished with the S (split) command:

$ C-a S

To switch over to the other region use <TAB> (the TAB key). At first there will be nothing in the new region. Just use the selection commands to bring up a window once you're over there. As of April 2006, there is talk of implementing vertical splitting.

To remove the current region: X.

naming
It is useful to assign a name to each window. Do