home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.os.linux
- Path: sparky!uunet!world!dsb
- From: dsb@world.std.com (David Boyce)
- Subject: Keeping track of Linux system configurations
- Message-ID: <Bt1wwz.78q@world.std.com>
- Organization: The World Public Access UNIX, Brookline, MA
- Date: Sun, 16 Aug 1992 00:48:34 GMT
- Lines: 251
-
- I posted an article a little while ago in which I basically
- said we should pay more attention to Linux configuration issues,
- meaning things like where files go, what their modes are, etc.
- Just to speak of devices: half of the existing users have
- serial devices starting at ttys0; the other half start
- at ttys1. Some of them use /dev/sd01 and some /dev/sda1.
- Some /dev/hd0, some /dev/hda. I myself know that I should
- be using /dev/fd0, but I don't know what its major and minor
- are. It's not mentioned in the FAQ; I could download the
- entire new mcc-interim release to see what fd0 is but I don't
- want to do that. Or I could post a note asking, but I don't want
- to waste hundreds or even thousands of dollars. Anyway, this
- kind of thing is irritating now and it will get worse as
- users proliferate and versions accumulate.
- So, in the spirit of Doing Something About It, I've written
- a script which I think could be useful for passing configuration
- info around. It's called "treestat" and I've included it below.
- Basically, it takes a snapshot of a set of files on your
- system and contains that snapshot within itself. Then if you move it
- to a different machine it will tell you how that system differs.
- There is a usage message (run it with no arguments to see it)
- and some additional info at the top of the script, but the basic usage
- of treestat is exceedingly simple. User A, wanting to record the
- state of his system, runs "cd /; treestat -record". He then gives
- treestat (which has just modified itself) to user B.
- If user B runs "treestat -compare" he will see on
- stdout the ways in which his files differ from those recorded
- by user A. Note that treestat is a configuration tool, not a versioning
- tool. Thus it does not check whether files are identical via checksums
- or the like. It cares only about the presence or absence of each
- pathname and whether it has the correct owner/group/mode/major/minor.
- Also note that it ignores any additional files user B might have
- that aren't part of the canonical set defined by user A.
-
- I'd appreciate it if (at least) the people in charge of mcc-interim,
- MJ, TAMU, etc. would give it a look and let me know if you find it
- useful, tell me of any improvements you'd like to see, bugs found, etc.
-
- My idea is that people making "standard" releases, such as
- mcc-interim, MJ, and TAMU would
-
- -> add treestat to their release
- -> run treestat -record just before making the release
- -> place it alone on their ftp site as "treestat.mcc.98.Z" or whatever.
-
- Then users who are running an old and maybe handmade version of linux
- could simply download treestat.mcc.98 and run it with -compare to see how
- they've diverged from mcc 0.98.
-
- ---------------- Cut Here ---------------------------------------------
- #!/bin/sh
- # Copyright (c) 1992 David Boyce
- # You may distribute this under the terms of the GNU General Public License,
- # version 2.
-
- # Run this with the -compare option to check your system.
-
- # This script was designed for Linux but should work on most *ixes,
- # modulo the awk and -g issues mentioned below.
- # The format used for describing files is the SVR4 package format. This was
- # chosen simply because it's common and well-known. The format is pretty
- # self-explanatory. The output from -compare is simply a normal diff between
- # two SVR4 package format files.
- # This might have been more elegant as a perl script, but the whole point
- # requires assuming as few tools and as few nonstandard features as possible.
- # As far as I know, it requires only sh, awk, ls, cat, xargs, and diff to run
- # on the local system. Generating a profile requires a few more but then you
- # expect everything to be in place there. As for special features, it requires
- # that the version of awk be either GNU awk (gawk) or the "new awk" (aka nawk)
- # shipped with SVR4. Also, the sense of the -g flag to ls is inverted between
- # SysV and BSD. I set it up in the BSD way, which also works with GNU ls and
- # thus Linux. On SysV machines you might have to remove the -g flag.
-
- usage()
- {
- cat <<CATEOF
- Usage: $ARG0 -compare|-fixscript|-record|-version|-printcanon
- Exactly one of the above options must be used.
- -compare compares the system description contained in this script against the
- system it's running on. Only files included in the canonical list within
- the script are compared; extra files on the local system are ignored.
- NOTE: Use "$ARG0 -compare" to check your system.
- -fixscript is like -compare but its output is in the form of a shell script
- to bring local modes into line with the canonical. I.e.
- "$ARG0 -fixscript | sh -xe" will normalize your local file modes.
- -record causes $ARG0 TO REPLACE ITSELF with a new version that describes
- the current system. By default the list of files is derived via an
- internal "find \`pwd\` -print | egrep -v '^/tmp|^/usr/tmp|^/usr/src|...'"
- but you can generate any file list you like by any method you like and
- pipe it to stdin, and that will be used instead. Note that supplied
- filenames must be rooted. Typical usage: "cd /; $ARG0 -record".
- Only people creating a canonical system description need this.
- -version simply prints out the name of the system currently described.
- -printcanon causes the canonical system description within the script to be
- printed to stdout.
- CATEOF
- exit 1
- }
-
- # Convert "ls -dilsg" output to SVR4 "package" format.
- pkgfmt()
- {
- awk "
- function mode(perms) {
- extra = 0;
- perms = substr(perms, 2);
- gsub(\"S\", \"s\", perms);
- gsub(\"t\", \"s\", perms);
- gsub(\"T\", \"s\", perms);
- if(substr(perms, 3, 1) == \"s\") extra += 4;
- if(substr(perms, 6, 1) == \"s\") extra += 2;
- if(substr(perms, 9, 1) == \"s\") extra += 1;
- gsub(\"s\", \"x\", perms);
- gsub(\"rwx\", \"7\", perms);
- gsub(\"rw-\", \"6\", perms);
- gsub(\"r-x\", \"5\", perms);
- gsub(\"r--\", \"4\", perms);
- gsub(\"-wx\", \"3\", perms);
- gsub(\"-w-\", \"2\", perms);
- gsub(\"--x\", \"1\", perms);
- gsub(\"---\", \"0\", perms);
- return extra perms;
- }
- function ftype(perms, links, inode, fname) {
- type = substr(perms,1,1);
- sub(\"-\",\"f\",type);
- sub(\"l\",\"s\",type);
- if(links > 1) {
- if(inodemap[inode]) {
- type = \"l\";
- symval = inodemap[inode];
- } else {
- inodemap[inode] = fname;
- }
- }
- return type;
- }
- {
- inode = \$1;
- fld3 = \$3;
- links = \$4;
- owner = \$5;
- group = \$6;
- devval = \$7 \$8;
- fname = substr(\$11, 2);
- if(length(fname) < 1) next;
- devname = substr(\$12, 2);
- symval = \$13
- }
- {
- type = ftype(fld3, links, inode, fname);
- if((type == \"s\") || (type == \"l\")) {
- print type,\"none\",fname \"=\" symval,owner,group,mode(fld3);
- } else if((type == \"b\") || (type == \"c\")) {
- print type,devval,devname,owner,group,mode(fld3);
- } else {
- print type,\"none\",fname,owner,group,mode(fld3);
- }
- }
- "
- }
-
- # Query user for data.
- resp() { echo "$1"; read $2; }
-
- record()
- {
- set -e
- NEWVERS=$RMTMPDIR/$ARG0
- PWD=${PWD:-`pwd`}
- resp "Enter an identifying name/version for this system's $PWD: \c" \
- SNAPSHOT </dev/tty
- chmod u+w $0
- cp $0 $TMPDIR
- awk "/^exit 0/{print; exit} {print}" < $0 > $NEWVERS
- echo "$SYSMARK $SNAPSHOT" >> $NEWVERS
- if tty -s ; then
- find $PWD -print |\
- egrep -v "$ARG0|^/tmp/|^/usr/tmp/|^/usr/src/|^/usr/spool/" |\
- egrep -v "^/usr/man/cat" |\
- sort |\
- xargs ls -dilsg |\
- pkgfmt >> $NEWVERS
- else
- sort | xargs ls -dilsg | pkgfmt >> $NEWVERS
- fi
- if cat $NEWVERS > $0; then
- rm -f $NEWVERS
- fi
- }
-
- printcanon()
- {
- awk <$0 '{if(data) print} /^exit 0/{data=1}'
- }
-
- compare()
- {
- printcanon > $CANON
- echo "$SYSMARK local" > $LOCAL
- awk 'NR>1 {split($3,a,"="); print "/" a[1]}' < $CANON |\
- xargs ls -dilsg 2>/dev/null |\
- pkgfmt >> $LOCAL
- diff $CANON $LOCAL
- }
-
- fixscript()
- {
- while read FIRST TYPE MM FNAME OWNER GROUP MODE; do
- case $FIRST=-=$TYPE in
- \<=-=[fdbc])
- case $TYPE=-=$MM in
- [bc]=-=*,*)
- echo rm -f /$FNAME '&&' mknod /$FNAME $TYPE \
- `echo $MM | awk -F, '{print $1,$2}'`
- ;;
- esac
- if [ -f /$FNAME -o "$MM" != "none" ]; then
- echo chown $OWNER /$FNAME
- echo chgrp $GROUP /$FNAME
- echo chmod $MODE /$FNAME
- else
- echo ": Missing: /$FNAME"
- fi
- ;;
- esac
- done
- }
-
- ARG0=`basename $0`
- TMPDIR=${TMPDIR:-/tmp}
- RMTMPDIR=$TMPDIR/tmp.$$
- LOCAL=$RMTMPDIR/local.$ARG0
- CANON=$RMTMPDIR/canon.$ARG0
- SYSMARK="System:"
-
- mkdir -p $RMTMPDIR 2>/dev/null
-
- case "$1" in
- -c*) compare ;;
- -f*) compare | fixscript ;;
- -p*) printcanon ;;
- -r*) record ;;
- -v*) egrep "^$SYSMARK" $0 ;;
- *) usage ;;
- esac
-
- rm -rf $RMTMPDIR
- exit 0 # This must remain as the last line!
- --
- David Boyce dsb@world.std.com 617-576-1540
-