You’ve Got Mail

This month, I've decided to break with our usual format and instead answer a few of the questions that I have received via e-mail. All of these concern system administration. The first one deals with the recently released 2.4 Linux kernel.

This month, I’ve decided to break with our usual format and instead answer a few of the questions that I have received via e-mail. All of these concern system administration. The first one deals with the recently released 2.4 Linux kernel.

How will the 2.4 kernel affect system administrators? Should I install it right away?

The 2.4 kernel will affect sysadmins in three main ways. First, the 2.4 kernel adds or improves support for many important system facilities. Systems can now contain more memory (up to 64 GB), larger files (the 2 GB limit is a thing of the past), multiple Ethernet adapters (up to 16), and so on. Support for new device types include USB and infrared. The 2.4 kernel will make a system administrator’s job easier by eliminating bothersome limitations.

Secondly, there are many important reliability, performance, and functionality improvements in 2.4. Perhaps most important to a system administrator are those that now allow NFS version 3 shares to be mounted on a Linux system (e.g., filesystems exported from Solaris, AIX, and other Unix systems using NFS3).

Finally, there are a number of enhancements that provide important new functionality; you will have to learn some new commands and techniques to administer them. The best example of this is the rewritten network layer, which separates the packet filtering and network address translation functions into distinct facilities. The latter item, which is used for IP masquerading, introduces a new tool called iptables, which will eventually replace ipchains (it is fortunate that iptables is backward compatible).

Another, simpler, example of this type is support for multiple mount points. Under the 2.4 kernel, filesystems may be mounted in more than one location. All instances of the filesystem are, in reality, the same file; multiple mount points simply provide multiple paths to the same data.

See the cover story in the January issue of Linux Magazine for a discussion of all the important features of the 2.4 kernel.

As to when you should install the 2.4 kernel, I have two answers. Install it right away but only on a test system. Now is definitely the time to start experimenting and learning its new features. However, I would suggest that you wait a couple of months before putting it on any important production systems. Personally, I want to be certain that the most egregious bugs have been identified and fixed before risking those systems.

The next few questions deal with important administrative utilities.

Other than using foreach, how can I run the same command on a group of files?

What you want is xargs, a tool that can run a command on any group of objects. xargs is typically used at the end of a pipe, and you specify the command you want to run as its argument. xargs will then append the items passed to it, via standard input, to that command. Here is a simple example using xargs:

$ls-1 test00* |xargstail -n5

This command will cause the last five lines of each file returned by the ls command to be displayed. Another example is shown in Figure One.

Figure One: Another Example of xargs

# ps -aux | egrep “(game1|game2|game3)” | grep -v grep | \
awk ‘{print $2}’ | xargs renice +10

This command lowers the priority of all processes running any of the specified games. The initial pipe gets the appropriate process IDs from the output of the ps command. Since the renice command takes multiple PIDs as its arguments, it is safe to send all of them to the command at once. If you want to send the arguments to the command one by one, you can use the -n option. This tells xargs to send the items to the specified command in groups of the size specified as the option’s argument (the long form option is –max-args); -n1 would send them one at a time.

You can also tell xargs to place each incoming line of input in the middle of the command to be executed by using the -i option, as shown in Figure Two.

Figure Two: Yet Another Example of xargs

$ ls -1 *.dat | xargs -i /bin/bash -c \
“sort {} | uniq > junk.junk ; mv junk.junk {}”

This command sorts and removes duplicate lines from each .dat file in the current directory. The -i option (–replace) to xargs causes each line of standard input to be substituted into the command wherever the curly braces occur. The command to run is specified as the argument to xargs-c option (enclosed in quotes); this is necessary since the command contains pipes and I/O redirection (which would otherwise apply to the xargs command itself). Note that -i sends distinct lines of input to the command and not individual items from a list.

Two other useful options are -t (–verbose), which displays each command before executing it, and -p (–prompt), which asks for confirmation before running each command.

A user brought me a printout someone had sent him. It had four pages printed on each sheet. Now he wants to print files like this. What command does this?

The command you want is mpage, which can print multiple pages from text or Postscript files on a single sheet of paper. You specify the number of pages per sheet with numeric options: -1, -2, -4 (the default) or -8 (very small print).

Other useful options are: -P to specify a desired printer, -f to wrap lines to page width, and -j to print a range of pages (e.g., -j1-10 prints just the first 10 pages).

The mpage command is usually included in Linux distributions but may not be installed by default. It is also readily available on the Internet.

Sometimes when I want to unmount a filesystem, I get an error that it’s busy. How can I find out who is using it?

You are referring to a situation like this:

# umount /leda
umount: /leda: device is busy

As you point out, this error message means that some process is using a file or directory under /leda. You can force the umount with -f if you want to, but are risking data loss if you do. Alternatively, you can use the fuser command, as shown in Figure Three, to find out who is using the filesystem. The -m option says to check all files in the specified filesystem, and -v requests verbose output (which is fuser‘s most useful mode).

Figure Three: The fuser Command

# fuser -v -m /leda
/leda chavez 5299 ..c.. tcsh
jones 5378 ..c.. tcsh
jones 5396 f.c.. ls

We can see that there are two users using items in the filesystem. The access code letters indicate the type of use: c means current working directory, e means executing a file, f means an open file, m means an mmap‘ed file/ shared library, and r means the root filesystem. Thus, in this case, user chavez has her current directory under /leda, and user jones has his current directory under /leda and is running an ls command on some directory in the filesystem. Note that the command does not tell us which specific file and directories are in use.

You can use a command like this to kill the processes that are using the specified filesystem:

#fuser -k -s -m /leda

where -k says to kill the processes, and -s suppresses command output. If you want to be more cautious, add -i to confirm each process kill. Of course, it would be nice to send a message to users (thus allowing them a little time to exit gracefully) before running such a draconian command.

How can I prevent a user from killing a script?

There are a variety of solutions to this problem. My solution is to use Perl for scripting since it has very robust signal handling capabilities. We’ll use the simple Perl script in Listing One for this discussion, a demo script that is designed to illustrate Perl’s signal handling facilities.

Listing One: A Sample Perl Script

# sig.pl

$SIG{‘TERM’} = ‘s1′;
$SIG{‘USR1′} = \&s2 ;
$SIG{‘QUIT’} = sub { $goofball++ } ;

sleep 100;
print “Still sleepy…\n”;

$SIG{‘USR1′} = ‘IGNORE’;

sleep 100;
print “Awake now!!\n”;

sub s1 { print “Caught TERM …\n”; }
sub s2 { print “Received USR1 …\n”; }

Perl uses the built-in %SIG hash to define signal-handling behavior; the various signal names provide the key values. By default, a Perl script will respond to all signals it receives in the default manner. Thus, an interrupt signal (INT), which might be received when a user types Control-C, will kill the script. However, signal-handling subroutines may be defined for each signal. If one has been defined, that subroutine will be called each time a process running the script receives the specified signal.

You define a signal handler by setting the value of its hash element to the subroutine you want to use, as in the first three non-comment lines in Listing One. They specify that the subroutines s1 and s2 will be used for the TERM and USR1 signals, respectively (note the two equivalent syntax forms), and that the value of the variable $goofball will be increased each time a QUIT signal is received (the subroutine is defined as part of the Perl statement defining the signal handler).

Specifying the values IGNORE and DEFAULT as the signal handler (also illustrated in the script) causes the corresponding signal to be ignored and handled in the normal manner, respectively. Our script initially ignores the interrupt (INT) signal (this is the signal sent by the kill command executed without an option).

This script defines four signal handlers, sleeps, and then prints a message. (In a real script, however, whatever you wanted to do would happen here.) Next, two of the signal handlers are redefined; the TERM signal is no longer handled, its default behavior returns, and the USR1 signal is ignored. The script sleeps again, prints a final message when it wakes up, and exits.

The remainder of the script defines the two signal handling subroutines, s1 and s1, both of which simply print a message in this example.

Let’s watch the script in action, first without interruption:

$ sig.pl
Still sleepy…
Awake now!!

Now we will run it in the background and send it some signals:

$ sig.pl &
[1] 13254
$ kill -INT 13254
$ kill -INT 13254
$ kill -USR1 13254
Received USR1 …
Still sleepy…
$ kill -USR1 13254
Awake now!!

We see that the INT signal is ignored as the script specifies. The first USR1 signal causes the sleep command to be interrupted (terminated), and the subroutine s2 runs, displaying its message. After subroutine s2 finishes, the script resumes execution, starting at the line after the one that was interrupted; the first print command runs. Next, the two signal handlers are redefined, and the subsequent USR1 signal is ignored. The script finishes the second sleep command and then terminates normally.

If we send a series of termination (TERM) signals, the process is somewhat different:

$ sig.pl &
[1] 13638
$ kill -TERM 13638
Caught TERM …
Still sleepy…
$ kill -TERM 13638
[1] Terminated sig.pl

The first TERM signal is caught, and the subroutine s1 runs (printing the corresponding message). The script continues at the print statement. Next, the second TERM signal kills the script (since that signal’s default functioning has been restored).

The final two items are in response to letters regarding previous columns.

The swatch Facility Configuration File

Nick DeClario has pointed out that the latest version of the swatch log file monitoring facility (version 3) uses a different configuration file format than the one illustrated in the March 2000 issue of this magazine. That example won’t work unless you specify the –old-style-config option to the swatch command. See Listing Two for Nick’s updated configuration file.

Listing Two: The Updated swatch Config File

watchfor /FAILED LOGIN 3 .* FOR root/
exec=xmessage root login failure over

watchfor /useradd/

watchfor /file system full/

watchfor /repeated [1-9][0-9][0-9] times/

Who is Mr. Proper?

Several readers answered my question about the origins of mrproper in the Linux kernel build procedure (as in make mrproper); thank you Pekka Nirranen, Joseph Pingenot, and Patrick Scheller. Apparently, Mr Proper (Meister Proper) is the name of a German kitchen cleaner (similar to the American product Mr. Clean). It was frequently advertised on Finnish television during Linus’ formative years.

Thanks also to Bob Goolsby who speculated on the name’s origin. Although his musings on the subject were not correct, they did remind me of a beloved book from my childhood, Mr. Popper’s Penguins.

Æleen Frisch is the author of Essential System Administration. She can be reached at aefrisch@lorentzian.com.

Comments are closed.