>>>>> "Rolf" == Rolf Welde Skeie <[EMAIL PROTECTED]> writes:
Rolf> 1) /etc/rc.d/init.d/autofs startup script did not handle
Rolf> correctly the fact that I wanted to use the NIS maps for all
Rolf> auto.* references. It even managed to do things like
Rolf> "automount ... yp /etc/auto.home" which is a nonsense
Rolf> combination of arguments. How does one go about the issue of
Rolf> using files, NIS or the combination? What good is the
Rolf> /etc/nsswitch.conf automount entry since it is not consulted
Rolf> by the startup script where the automounter is started? And
Rolf> what about updating the auto.master in NIS; one has to restart
Rolf> autofs for this to take effect? (I edited the startup script
Rolf> and moved away all /etc/auto.* files on the clients to make it
Rolf> work as desired).
I had the same problem and solved it by modifying the autofs script in
a general way. It uses the information in nsswitch.conf to decide
where to look for the maps. Moreover, with the help of a Perl script
(automap), it can fake Sun direct maps. I'm sendind the autofs and
automap script along with our local customization for the Linux
clients. For three months we're being able to integrate Linux clients
on a NIS domain which incorporate Solaris, SunOS, HP-UX, OSF, and AIX
machines. I hope it helps somebody else.
Gustavo.
#! /bin/bash
#
# $Id: autofs,v 1.1 1999/03/04 13:38:30 gustavo Exp $
# $-Id: rc.autofs,v 1.3 1998/03/28 03:22:38 hpa Exp $
#
# rc file for automount using a Sun-style "master map".
# We first look for a local /etc/auto.master, then a YP
# map with that name
#
# chkconfig: - 72 08
# description: automatically mounts filesystems when you use \
# them, and unmounts them later when you are not using them.
# processname: automount
# Note that there may be multiple processes names automount
# config: /etc/auto.master
# Note that all other config files are automatically reloaded
# and may be different on different systems; we can ignore them
# here
# Source function library.
. /etc/rc.d/init.d/functions
test -f /usr/sbin/automount || exit 0
#
# We can add local options here
# e.g. localoptions='rsize=8192,wsize=8192'
#
localoptions=''
# See where do we get info from in the name service switch file.
if [ -f /etc/nsswitch.conf ]; then
nsorder=`sed -n '/^automount:/s/automount:\(.*\)/\1/p' /etc//nsswitch.conf`
fi
# If nsswitch.conf doesn't exist or doesn't define the order for automount
# use a default order.
if [ -z "$nsorder" ]; then
nsorder="files nis"
fi
# This function receives a map name and tries to tell if it's a file
# map, a program map, or a nis map according to its name and $nsorder
# as defined above. It tells it by returning two words. The first is
# one of "file", "program", "yp", or "notfound" for a map not found. The
# second is the map name.
function getmap() {
case $1 in
*/*) # Must be a file when the name contains a slash.
if [ -x $1 ]; then
echo "program $1"
elif [ -f $1 ]; then
echo "file $1"
else
echo "notfound"
fi
return
;;
esac
for db in $nsorder; do
case $db in
files)
if [ -x /etc/$1 ]; then
echo "program /etc/$1"
return
elif [ -f /etc/$1 ]; then
echo "file /etc/$1"
return
fi
;;
nis|yp)
if ypwhich -m $1 >/dev/null 2>&1; then
echo "yp $1"
return
fi
;;
nisplus|nis+)
# Not implemented - SKIP
;;
'[NOTFOUND=return]')
break
;;
*)
# Unknown or invalid spec - SKIP(?)
esac
done
echo "notfound"
}
#
# This function will build a list of automount commands to execute in
# order # to activate all the mount points. It is used to figure out
# the difference of automount points in case of a reload
#
function getmounts()
{
set `getmap auto.master`
case $1 in
file|program)
sed -e '/^#/d' -e '/^$/d' $2
;;
yp)
ypcat -k $2
;;
*)
return
esac | \
while read dir map options
do
if [ -z "$dir" -o -z "$map" -o x`echo "$map" | cut -c1` = 'x-' ]
then continue
fi
options=`echo "$options" | sed -e 's/\(^\|[ \t]\)-/\1/g'`
set `getmap $map`
case $dir in
/-)
# Direct maps aren't directly supported. They're faked.
case $1 in
program)
# The program map must create the appropriate
# symlinks. Otherwise we can't rely on it.
if $2 -createlinks; then
test -e /- || mkdir /-
if [ -d /- ]; then
echo "automount /- $1 $2 $options $localoptions"
else
echo "autofs: /- should be a directory" >&2
fi
fi
;;
*)
echo "autofs: direct maps must be of the program kind" >&2
esac
;;
*)
case $1 in
file|program|yp)
echo "automount $dir $1 $2 $options $localoptions"
;;
*)
# Do nothing
esac
esac
done
}
#
# See how we were called.
#
case "$1" in
start)
# Check if the automounter is already running?
if [ ! -f /var/lock/subsys/automount ]; then
echo 'Starting automounter: '
getmounts | sh
touch /var/lock/subsys/automount
fi
;;
stop)
kill -TERM $(/sbin/pidof /usr/sbin/automount)
rm -f /var/lock/subsys/automount
;;
reload|restart)
if [ ! -f /var/lock/subsys/automount ]; then
echo "Automounter not running"
exit 1
fi
echo "Checking for changes to /etc/auto.master ...."
TMP1=`mktemp /tmp/autofs.XXXXXX` || { echo "could not make temp file" >&2;
exit 1; }
TMP2=`mktemp /tmp/autofs.XXXXXX` || { echo "could not make temp file" >&2;
exit 1; }
getmounts >$TMP1
ps ax|grep "[0-9]:[0-9][0-9] automount " | (
while read pid tt stat time command; do
echo "$command" >>$TMP2
if ! grep -q "^$command" $TMP2; then
kill -USR2 $pid
echo "Stop $command"
fi
done
)
cat $TMP1 | ( while read x; do
if ! grep -q "^$x" $TMP2; then
$x
echo "Start $x"
fi
done )
rm $TMP1 $TMP2
;;
status)
echo "Configured Mount Points:"
getmounts
echo ""
echo "Active Mount Points:"
ps ax|grep "[0-9]:[0-9][0-9] automount " | (
while read pid tt stat time command; do echo $command; done
)
;;
*)
echo "Usage: /etc/init.d/autofs {start|stop|restart|reload|status}"
exit 1
esac
exit 0
#!/usr/bin/perl -w
# automap - pre-process Sun automounter maps for Linux
# $Id: automap,v 1.4 1999/03/05 14:45:49 gustavo Exp $
use strict;
use Sys::Hostname;
$ENV{PATH} = '/bin:/usr/bin';
# Constants
my $usage = "usage: $0 [KEY|-createlinks] {[-file MAP] [-yp MAP]}*\n";
my $prefix = '/-'; # default mountpoint prefix
my @netmask = (255, 255, 248, 0); # local netmask
my $localnet = hostnet(hostname()); # the local network
# OBS: I fixed the netmask value for two reasons. First, I don't know
# of a way to obtain it reliably. Second, if there is a way, it must
# be fast, because this script will be called whenever an automount
# may happen and I don't want to fork many processes just to solve
# this problem since in the majority of cases the netmask is fixed for
# a whole network. Note also that I'm assuming that this host has
# only one network interface. Multihomed hosts may use different
# netmasks for each interface. The adaptation of this script to work
# in this case is left as an exercise to the reader. :-(
# The first argument must be the option -createlinks or a KEY to be
# looked for in the maps defined by the remaining arguments.
my $key = shift or die $usage;
# The remaining arguments are map specifications. Each spec is a pair
# consisting of a database-id (-file or -yp) and the name of the map.
# Checking the number of arguments left to be even simplifies the
# implementation of the subroutines createlinks and match below.
die $usage unless (@ARGV % 2) == 0;
if ($key eq '-createlinks') {
createlinks(@ARGV);
} else {
# Keys of the direct map are received with +'s substituted
# for /'s because of our tricks above. We have to covert them
# back in order to search them in the maps.
$key =~ tr@+@/@;
match($key, @ARGV);
}
# Can't happen
exit(1);
##############################
# Subroutines
# This procedure walks through the maps specified creating a symlink
# for each of their entries. The symlinks point to a faked indirect
# automount-point. This function is terminal.
sub createlinks {
while (@_) {
my $bd = shift;
my $map = shift;
if ($bd eq '-file') {
# $map already contains the file name
} elsif ($bd eq '-yp') {
# transform $map to suit it to the open below.
$map = "ypcat -k $map 2>/dev/null |";
} else {
die $usage;
}
next unless open(MAP, $map);
while (<MAP>) {
my ($key) = split;
# $key must be an absolute path
next unless $key =~ m@(/[^/\s]+)+@;
# Fake the absolute path by substituting + for /
# and prefixing it with $prefix.
my $fake = $key;
$fake =~ tr@/@+@;
$fake = $prefix . '/' . $fake;
if (-l $key) {
warn "$0: $key should point to $fake\n"
unless readlink($key) eq $fake;
} elsif (-e $key) {
warn "$0: $key should be a link or nothing\n";
} elsif (not symlink($fake, $key)) {
warn "$0: can't symlink $fake, $key\n";
}
}
close(MAP);
}
exit(0);
}
# This function receives a $key and a list of map specifications when
# the $key is to be looked for. If the key is found its data is
# pruned to remove all but one NFS server and the pruned data is
# printed on the standard output. This function is terminal.
sub match {
my $key = shift;
while (@_) {
my $bd = shift;
my $map = shift;
if ($bd eq '-file') {
next unless open(MAP, $map);
while (<MAP>) {
my ($head, $tail) = split(' ', $_, 2);
next unless $head eq $key;
chomp $tail;
automount($key, $tail);
}
close(MAP);
} elsif ($bd eq '-yp') {
# yp map
my $tail = `ypmatch $key $map 2>/dev/null`;
next if $?;
chomp $tail;
automount($key, $tail);
} else {
die $usage;
}
}
# Key wasn't found.
exit 1;
}
# This function receives the $key and the data of an entry of a direct
# map and tries to output a proper automount command. This function
# is terminal
sub automount {
my $key = shift;
my @data = split ' ', shift;
my $options = ($data[0] =~ /^-/) ? shift @data : '';
my %neighbor; # NFS servers in the local network
my %foreign; # NFS servers in foreing networks
# Now, each @data component must be an alternative NFS share
# with the following syntax: HOST{,HOST}:PATH. We walk through
# them populating the %neighbor and %foreign hashes as we go.
foreach (@data) {
if (/^\//) {
# Ooops. This must be a multimount entry and we don't
# support this yet. We have two choices: either die or
# warn about this and do only to topmost mount. I think
# it's better to warn and do part of what the user wants.
warn "$0: multimounts at $key aren't fully supported\n";
last;
}
my ($hosts, $path) = split(/:/, $_, 2);
# substitute $key for the ampersand notation
$path =~ s@&@$key@g;
$path =~ s@:@/@g;
foreach (split /,/, $hosts) {
if ($localnet eq hostnet($_)) {
$neighbor{$_} = $path;
} else {
$foreign{$_} = $path;
}
}
}
# Chose a random server trying to balance the load. Give
# preference to a server in the local network.
if (%neighbor) {
my @keys = keys %neighbor;
my $host = $keys[rand(@keys)];
print "$options $host:$neighbor{$host}\n";
exit 0;
} elsif (%foreign) {
my @keys = keys %foreign;
my $host = $keys[rand(@keys)];
print "$options $host:$foreign{$host}\n";
exit 0;
} else {
exit 1;
}
}
# This function receives a hostname and returns the dot-notation of
# the network it's in.
sub hostnet {
my $rawaddr = gethostbyname shift;
return 0 unless defined $rawaddr;
my @addr = unpack('C4', $rawaddr);
my $i;
for $i (0 .. 3) {
$addr[$i] &= $netmask[$i];
}
return join '.', @addr;
}
# Format of this file:
# mountpoint map options
# For details of the format look at autofs(8).
/home auto.home
/net /etc/auto.net -ro
/- /etc/auto.direct -ro
/n auto.net
#!/bin/sh
/sbin/automap "$1" -yp auto.net.Linux -yp auto.net.common
#!/bin/sh
/sbin/automap "$1" -yp auto.direct.Linux -yp auto.direct.common