Replacing
rdist and ftp with scp and Associated Utilities
Michael Watson
At some point, manually logging into every server to repetitively
make changes gets rather tiresome. Therefore, my team decided to
automate these procedures. With thirty-plus Solaris systems, we
began by utilizing a set of simple ftp scripts (see the Listings
at www.sysadminmag.com) to get, display (in the case of text
files), or put files to some or all of our servers.
Although our servers are not connected directly to the Internet,
root logins for telnet or ftp are nonetheless forbidden.
This somewhat limits the utility of ftp for system configuration
files. We also have shared directories from our NIS master to all
of the other servers, but in either case, we still had to log onto
each server to deal with root-level files, whether they were available
by NFS mounts or by ftping them to a local directory.
Moving On Up with ssh2 and scp
Because we were installing ssh 2.0.13 anyway, we enabled
root logins in the /etc/ssh2/sshd2_config file. While we
would like to disable root ssh logins (in order to get scp
access for root) we are currently living somewhat uneasily with
this configuration. (scp is the secure equivalent of the
classic UNIX rcp remote file access utility.)
Essentially, the scp scripts were a refinement of the original
ftp scripts, and they serve three functions: 1) collection
of an identically-named file from all of the servers, which are
then retained with a suffix comprising the server's hostname;
2) redistribution of saved or individually tailored files back to
all or a subset of the servers; or 3) simply to distribute an identical
file to the servers, à la rdist.
We do not have any trusted hosts, but we do have a simplified
system by which certain servers that share certain applications,
or teams that utilize them, have the same root passwords. If each
were unique, not only would it be a major problem remembering them,
but there would be less utility in scripting file transfers. This
is especially true in our case because no passwords are allowed
to be committed to a file -- they must be manually entered each
time a script is run. After all, typing in a password for each server
is what we are trying to get away from.
The Centralized Economy
Once we had the basic infrastructure in place, a few logical extensions
came to mind. The first is to use the scp scripts to facilitate
maintenance of scripts and configuration files across the server
set. This is relatively easy to do, and we settled on a system whereby
our collection script (see Listing 6) would transfer files of the
same name to our "master" server, an Ultra-5 in this case,
place them in whatever directory was specified, and append the name
of the server from which the file originated to the end of the filename.
This allowed us to quickly view and individually modify the files,
and we could then return individualized files to each respective
server using scp1m-put (see Listing 7). If the substitution
of all files by a single file is desired, scp1m-rdist (see
Listing 8) provides that function.
We then had distribution abilities, but any updates that required
action on the server still required that we log in to each server
to perform the tasks.
Scripting with Intent to Distribute
Out of this was born the cron-based update scripts. We set up
two cron entries, one to run once a day for those jobs that shouldn't
be messing with prime time activities, and the other to run every
five minutes. The original design had the cron job execute if it
was present, but our SNMP guys complained about the errors cron
would register when no script was there to be executed. This led
to the development of a permanent script for each cron job, which
exits cleanly if there is no script to be executed. An additional
benefit was that if scp was not carrying forward the original
permissions on the file (which might occasionally happen when scping
a single file by hand and forgetting the -p option), the
permanent script now chmod's the script before running
it.
We now had to create a script to be executed on all or some subset
of our servers, scp it into the directory on the target system(s)
(set up for this purpose under the name sysupdt.qh or .qd
depending on how soon we want it executed), and then wait for it
to run. This is relatively unsophisticated because failing to wait
for the script to run before scping over another will wipe
out the one waiting. You can even do this multiple times!
After creating a few scripts to be run by our cron job on the
remote systems, we realized that using the sysupdt.qh file
every time on our central server was preventing us from saving and
easily recognizing the scripts we had created. Thus, we stared creating
descriptively named scripts we could use to reduce reinventing-the-wheel
overhead. When necessary to tailor scripts individually for each
destination server, we would append the server name to the script
(e.g., "dothis" script for "onthat" server would
be named "dothis.onthat"), which is how scp1m-put
(Listing 7) expects to see source filenames constructed. An example
of a single copy from the command line of the central server to
the file to be executed by our cron job on a destination server
would therefore look like:
>scp dothis.onthat root@destination-server:/.sysupdt/sysupdt.qh
On each server, the sysupdt.Q* scripts rename the scripts
they execute, and these are retained for 30 days. Cleanup is a part
of the daily sysupdt.QD execution. The /.sysupdt directory
is our default location on both our source and target servers.
Can Institutionalization Keep You SA[FN]E?
One example of how we put this to use is hardly a profound one,
but serves to simply illustrate a potential use of this infrastructure
(terminology that we are torn whether to describe as pedantic or
grandiose).
This was the development of a local log checking script. This
was exported to each of the servers by rdistall:
>./rdistall logchk /usr/local/bin/logchk
Next, the updates to root's crontab were distributed out,
to be executed by the cron jobs that run every five minutes:
>./rdistall cron.updt /.sysupdt/sysupdt.qh
However, the logchk cron entry executes at 23:59, so the
next morning we ran:
>./dailylogchk MMDDYY
where MMDDYY is yesterday's (or any previous day's date,
as we do on Monday for the previous three nights). This script calls
getall, passes the name and directory parameters that getall
needs, then permits examination of the files via "less",
and subsequently runs some additional checks via the scripts loginchk,
pscheck, cronchk, and dfkchk. cronchk
is a recent addition, and requires that Monday's checks be
run in chronological order.
Briefly, these extra scripts are:
loginchk -- Looks for native root logins, but su
will show them too, so they have to be tracked down and verified.
pscheck -- On Solaris, ptree is a variant of
ps. This is a cross-check, which would hopefully trip up
a ps replacement.
cronchk -- Differs for changes between the most-recent
and the next most recent crontabs for changes. We want to catch
unexpected ones.
dfkchk -- Parses df -k output for disk space
utilization greater than 90%.
shortlogchk -- Sometimes we forget and "q"
out of our less session. This then runs the above four scripts.
These illustrate the kinds of things we can do when we pull a
set of files from all, or a subset, of our servers. Examination
of such files on a single server or workstation is more efficient
than having them separated and trying to discover differences, similarities,
and discrepancies on a server-by-server basis.
Problems in Paradise
As in all endeavors, there are a few bugs that bite. Under Solaris
8 and ssh 2.0.13, the password that is passed into the scripts
without being displayed is nonetheless showing up when the script
executes the expect command. Oddly enough, we didn't
have this problem with a Solaris 2.6/OpenSSH 2.x combination. We
successfully tested a /dev/null redirection that we then
commented out in the scp1m-get script, but that suppressed
all output, including the output that might show any failures or
other anomalies. We hope, however, that a future revision of the
components we used under Solaris 8 will correct this problem. Let
us know if a solution is discovered.
Michael Watson liked computers better than his prospects with
his BS in Psychobiology, so he started out programming COBOL, assembler,
and Ada on a couple of coasts. He then suffered a brief digression
into Oracle programming before ending up in UNIX systems administration.
He now works as a consultant based in the middle of the country.
When working in the same place for long enough, he likes to write
labor-saving devices and contemplate whether he would really rather
be a commercial pilot.
|