Xref: utzoo news.software.b:7967 news.admin:14673 Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!hela!wotan.iti.org!scs From: scs@iti.org (Steve Simmons) Newsgroups: news.software.b,news.admin Subject: Re: Really funny jokes being missed Message-ID: Date: 27 May 91 03:55:40 GMT References: <28357D59.17BB@tct.com> <1991May26.082113@mccall.com> Sender: usenet@iti.org (Hela News Manager) Organization: Industrial Technology Institute Lines: 851 Nntp-Posting-Host: wotan.iti.org tp@mccall.com (Terry Poot) writes: >In article , tim@dell.co.uk (Tim Wright) writes: >>In mathew@mantis.co.uk (CNEWS MUST DIE!) writes: >>>chip@tct.com (Chip Salzenberg) writes: >>>> Administrators who get "bogus header" messages and don't pass them on >>>> deserve flamage. >> >>>Unfortunately, it seems there are quite a few sites out there whose system >>>administrators have better things to do with their time than read the log >>>files and send mail messages to people whose articles have been junked. >> >>You don't need to read the log files. I take it you do have access to awk, >>cron and mail. It can't be that hard to put together a small summarising >>script to mail you, can it ?? Quite a few sites conversely do take the time. >In my case, 2. If you have such a tool, why don't you send it to Henry or >Geoff so they can include it with C news? C news does not include such a >facility. Do you actually believe even a majority of C news admins will >take the time to write one? The following script generates a detailed report on news traffic and problems including header reports. It's by no means done, but it seems clear there's a need...the folks who've been beta testing it seem to like it. Patches will be appreciated, but be forewarned it's going to get a major rewrite Real Soon Now. #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'cnews.logrep' <<'END_OF_FILE' X: /bin/sh X# X# Shell script for cnews log reports X# X# This script scans the cnews data areas and looks for things that X# are out of whack. It reads some of the log files looking for X# interesting information. If there are no errors or oddities, it X# tells you so. This should be run immediately after the cnews daily X# 'newsdaily' script. It expects the logs to be named .o X# but you can change that by resetting the *LOG variables as shown X# below. X# X# One point of "philosophy": this whole script is built on the idea X# that silence is *not* golden. If things are OK, it explicitly X# tells you so. X# X# The log file analyzer is a big awk script. Make sure you understand X# awk associative arrays before attempting to modify it. X# X# $RCSfile: cnews.logrep,v $ $Revision: 0.16 $ X# X# $Author: news $ $Date: 91/04/22 11:15:10 $ X# X# $State: Exp $ $Locker: news $ X# X# $Log: cnews.logrep,v $ X# Revision 0.16 91/04/22 11:15:10 news X# Cleaned up extra backslashes. Added sendme processing with the ihaves. X# Made names of all log files explicit. X# X# Revision 0.15 91/04/22 10:03:59 news X# Added cancel and failed cancel reporting. X# X# Revision 0.14 91/04/22 09:12:14 news X# Got oldies number right. X# X# Revision 0.13 91/04/12 11:40:12 news X# Added reports on future dates and too-old dates, added notice on X# postings which lack message ids. X# X# Revision 0.12 91/04/11 16:46:08 news X# Added outgoing batch checking. X# X# Revision 0.11 91/04/11 16:33:33 news X# Many changes as per suggestions from Brendan Kehoe and Owen Medd. X# Many many changes. Many many many changes. X# X# Initialize the dirs, names of the logs, and variables X# X. /usr/lib/news/cnewsbin/config XPATH="$NEWSPATH:$NEWSBIN" Xexport PATH XSCRIPT=`basename $0` X# X# Shorthand names for standard C news locations X# XLOGDIR=$NEWSCTL XSYSFILE=${LOGDIR}/sys XINCOMING=${NEWSARTS}/in.coming XOUTGOING=${NEWSARGS}/out.going XBADBATCHES=${INCOMING}/bad X# X# If you are running RELAYNEWS as a daemon, uncomment this next line X# X#RELAYNEWS=1 X# X# When there are completely unrecognizable entries in the log, the X# normal procedure is to print them out in toto so you can extend X# this script to say something intelligent about them. But if X# there are hundreds, it can be overwhelming. These variables allow X# you to restrict the number you will print. X# XMAX_DEFECTS=5 XMAX_UNKNOWN=5 XMAX_MYSTERY_DASH=5 XMAX_MYSTERY=5 XMAX_NOPATH=5 X# X# If this is not where you put the old log files, adjust X# these locations and names accordingly X# XERRLOG=${LOGDIR}/errlog.o XNEWSLOG=${LOGDIR}/log.o XBATCHLOG=${NEWSCTL}/batchlog.o XBATCHPARMS=${NEWSCTL}/batchparms X# XNEWSMGR=news XHOSTNAME=`newshostname` XTEMPFILE=/tmp/${SCRIPT}.$$ Xset `date` XDATE="${1} ${2} ${3}, ${6}" Xtrap 'rm -f $TEMPFILE ; exit' 0 1 2 3 15 Xexec > $TEMPFILE X# X# Print preface. X# Xcat << EOF XThis is the news system status report for $DATE as Xgenerated by $0. X XEOF X# X# Errorcheck to be sure the error log exists. X# Xif [ "" = "$HOSTNAME" ] ; then X cat << EOF XThe news host name was not found. Please check the file X$NEWSCTL/whoami, and make sure the host name is set Xappropriately for your system (e.g, look at \'uuname -l\' and X\'uname -n\'. The report will be somewhat incomplete. X XEOF Xfi X# X# Errorcheck to be sure the error log exists. X# Xif [ ! -f "$ERRLOG" ] ; then X cat << EOF XThe news error log ($ERRLOG) for was not found. XPlease check the news system and this script. X XEOF Xelse X # X # If the error log is empty, report that. Otherwise copy it to X # the news manager. In either case, give a nice prefatory remark. X # X SIZE=`wc -l < $ERRLOG` X SIZE=`echo $SIZE` X if [ $SIZE = 0 ] ; then X cat << EOF XThe news error log ($ERRLOG) shows no errors. X XEOF X else X # X # Give a nice prefatory remark, then copy the log to the news X # manager. Put beginning and end markers. X # X cat << EOF XThe news error log ($ERRLOG) has $SIZE complaints. A Xcopy of the error log is included below: X X$ERRLOG: XEOF X cat < ${ERRLOG} X cat << EOF XEnd of $ERRLOG X XEOF X fi Xfi X# X# Report on bad batches left lying around X# Xif [ -d ${BADBATCHES} ] ; then X ( X cd $BADBATCHES X COUNT=`ls | wc -l` X COUNT=`echo $COUNT` X if [ $COUNT = 0 ] ; then X echo "There are no bad batches being held in $BADBATCHES." X else X echo "There are $COUNT bad batches being held in $BADBATCHES:" X if [ $COUNT -gt 10 ] ; then X ls -C X else X ls -l X fi X fi X ) Xelse X echo "Could not find bad batches directory ($BADBATCHES)!" Xfi Xecho "" X# X# Report on old nrun files. X# Xif [ ! -d $INCOMING ] ; then X echo "Could not find incoming directory ($INCOMING)!" Xelse X ( X cd $INCOMING X COUNT=`find . -name 'n*' -type f -mtime +1 -print | wc -l` X COUNT=`echo $COUNT` X if [ $COUNT != 0 ] ; then X echo "There seem to be old run fragments left in ${INCOMING}:" X echo "" X ls -ls n* X else X echo "There are no old run fragments left in ${INCOMING}." X fi X echo "" X # X # Report on old batch files. X # X LIST=`find . -name "[1-9]*" -type f -mtime +1 -print` X COUNT=`echo $LIST | wc -w` X COUNT=`echo $COUNT` X if [ $COUNT != 0 ] ; then X cat << EOF XThere seem to be $COUNT old incoming batches left in ${INCOMING}. XYou should check to see if unbatching is being done properly. The Xold batches are: X XEOF X if [ $COUNT -gt 10 ] ; then X ls -C $LIST X else X ls -ld $LIST X fi X else X echo "There are no old batches left in ${INCOMING}." X fi X ) Xfi Xecho "" X# X# Report on the status of batching. If the batchparms files X# does not exist, simply state that we think no batching is X# going on. If it's there, try to report on batching. If your X# site doesn't do batching and you'd like to shut up this section X# of the report, rename $BATCHPARMS to $BATCHPARMS.sample. X# X# This needs to be expanded to report more fully on batch results.... X# Xif [ ! -f "$BATCHPARMS" ] ; then X echo "You do not appear to be doing any uucp batching (no batch" X echo "paramters file $BATCHPARMS)." Xelse X if [ ! -f "$BATCHLOG" ] ; then X echo "Could not process batch log ${BATCHLOG}." X else X # X # Report on stalled batching for outside sites. Report if the X # log does not exist. X # X COUNT=`grep "no recent movement" ${BATCHLOG} | wc -l` X COUNT=`echo $COUNT` X if [ $COUNT != 0 ] ; then X echo "The news batch queue is full for the following sites:" X grep "no recent movement" ${BATCHLOG} | awk '{ printf "%s\n", $1 }' | sort | uniq X else X echo "There are no full outgoing batch queues show in $BATCHLOG." X fi X fi Xfi Xecho "" X# X# Errorcheck to be sure the regular log exists. X# Xif [ ! -f "$NEWSLOG" ] ; then X cat << EOF XCould not process news log! X XThe standard news log ($NEWSLOG) was not found. XPlease check the news system and this script. X XEOF Xelse X # X # Generate traffic, activity, and oddity report. I am X # not a big awk fan, but gotta admit you can do a lot X # with associative arrays. X # X awk < $NEWSLOG ' XBEGIN { X accept_count = 0 X entry_count = 0 X ship_count = 0 X x_count = 0 X duplicate_count = 0 X ihave_count = 0 X sendme_count = 0 X unapproved_count = 0 X unsub_count = 0 X junk_count = 0 X local_articles = 0 X bad_header_count = 0 X empty_header_count = 0 X non_header_count = 0 X bad_date_count = 0 X no_msgid_count = 0 X unknown_no_count = 0 X future_count = 0 X oldies_count = 0 X cancel_count = 0 X precancel_count = 0 X nopath_count = 0 X mystery_dash_count = 0 X mystery_count = 0 X defect_count = 0 X hostname = "'$HOSTNAME'" X} X{ X # X # Count all entries, note and save defective ones X # X entry_count++ X if ( NF < 6 ) X { X defect_count++ X defective_entry[ $0 ]++ X } X else if ( $5 == "+" ) X { X # X # Track the accepted articles X # X accept_count++ X accept_host[ $4 ]++ X if ( NF > 6 ) X { X ship_count++ X shipfield = 7 + "'$RELAYNEWS'" X # X # Record which systems got articles X # X while ( shipfield <= NF ) X { X ship_list[ $shipfield ]++ X shipfield++ X } X } X # X # Track the number of local postings X # X if ( $4 == hostname ) X local_count++ X } X # X # Track all junked articles by reason junked. X # X else if ( $5 == "j" ) X { X junk_count++ X reason = 7 X junkfor="" X while ( reason <= NF ) X { X junkfor = junkfor $reason " " X reason++ X } X junk_reason[ junkfor ]++ X } X # X # Track ihave/sendme records X # X else if ( $5 == "i" ) X { X ihave_count++ X ihave_source[ $4 ]++ X } X else if ( $5 == "s" ) X { X sendme_count++ X sendme_source[ $4 ]++ X } X # X # Track the exceptions on a class-by-class basis X # X else if ( $5 == "-" ) X { X # X # Track the number of duplicates we get from various sites. X # X if ( $7 == "duplicate" ) X { X duplicate_count++ X duplicate_host[ $4 ]++ X } X # X # Track the number of unapproved articles and their sources. X # X else if ( $7 == "unapproved" ) X { X unapproved_count++ X unapproved_source[ $4 ]++ X unapproved_target[ $12 ]++ X } X # X # Lots of errors are no this, no that, etc. We process X # them all at once. X # X else if ( $7 == "no" ) X { X if ( $8 == "subscribed" ) X { X # X # Track the number of unsubscribed articles we X # get from various sites and the target group. X # X unsub_count++ X unsub_source[ $4 ]++ X unsub_target[ $11 ]++ X } X # X # These are needed for new pedantic Cnews. Over X # time these should decline. We track where the X # articles came from but not the message ids. If X # the admin is really interested, they can track X # them down by grepping the logfile for "no FOO" X # and the name of the offending host. X # X else if ( ( $8 == "Date:" ) || ( $8 == "@" ) || ( $8 == "From:" ) || ( $8 == "Subject:" ) ) X { X bad_header_count++ X bad_header_source[ $4 ]++ X } X else X # X # These are minus for unknown reason. An obvious X # candidate for mods to this script. X # X { X unknown_no_count++ X unknown_no_field[ $8 ]++ X unknown_no_entry[ $0 ]++ X } X } X # X # This next is a *severe* error! X # X else if ( ( $6 == "no" ) && ( $7 == "Message-ID:" ) ) X { X no_msgid_count++ X no_msgid_source[ $4 ]++ X } X # X # Other less serious errors X # X else if ( $7 == "empty" ) X { X empty_header_count++ X empty_header_field[ $8 ]++ X empty_header_source[ $4 ]++ X } X else if ( ( $9 == "contains" ) && ( $10 == "non-header" ) ) X { X non_header_count++ X non_header_source[ $4 ]++ X } X else if ( ( $7 == "unparsable" ) && ( $8 == "Date:" ) ) X { X bad_date_count++ X bad_date_source[ $4 ]++ X } X # X # Track the number of articles which we explicitly reject via X # x records in the active file. We do not track the specific X # groups for two reasons -- presumably since you xed it, you X # know what you reject; and it is hard to parse. X # X else if ( ( $7 == "all" ) && ( $8 == "groups" ) ) X { X x_count++ X } X # X # Track the articles which are too far in the future X # X else if ( ( $7 == "Date:" ) && ( $8 == "too" ) && ( $9 == "far" ) ) X { X future_count++ X future_source[ $4 ]++ X } X # X # Track the articles which are too old to be worth keeping X # I love this cnews feature -- it will probably keep things X # freer of loops than anything else. X # X else if ( ( $7 == "older" ) && ( $8 == "than" ) ) X { X oldies_count++ X oldies_source[ $4 ]++ X } X # X # Some articles come in sans Path: headers. This X # identifies them. X # X else if ( ( $7 == "no" ) && ( $7 == "Path:" ) && ( $8 == "header" ) ) X { X nopath_count++ X nopath_source[ $4 ]++ X } X # X # Any unrecognised "-" tag is kept here. As we find these X # they should be added to the things handled above. X # X else X { X mystery_dash_count++ X mystery_dash_entry[ $0 ]++ X } X } X # X # This counts cancel messages. They are not generated by X # standard C news, but by Dave Aldens relaynews daemon. X # X else if ( $5 == "c" ) X { X cancel_count++ X } X # X # This counts failed cancel messages. They are not generated X # by standard C news, but by Dave Aldens relaynews daemon. X # X else if ( $5 == "f" ) X { X precancel_count++ X } X # X # Any unrecognised tags get noted here. As we get these X # they sould be added to the things handled above. X # X else X { X mystery_count++ X mystery_tags[ $5 ]++ X mystery_entry[ $0 ]++ X } X} XEND { X printf "\nThere were %d entries in the standard log. Breakdown:\n", entry_count X if ( entry_count != 0 ) X { X # X # Report the data by categories. X # X # Local postings. It would be nice to report the newsgroups X # posted to, but that data is not in the log. X # X printf "\n%6d articles were posted from this site (%s)\n", local_count, hostname X # X # Next, where outside articles came from X # X printf "\n%6d incoming articles accepted for processing\n", accept_count X if ( accept_count > 0 ) X for ( host in accept_host ) X printf " %6d from %s\n", accept_host[ host ], host X printf "\n%6d of those were rejected as duplicates\n", duplicate_count X # X # Report number of duplicates and who gave them to us. X # X if ( duplicate_count > 0 ) X for ( host in duplicate_host ) X printf " %6d from %s\n", duplicate_host[ host ], host X # X # Ihave activity. X # X printf "\n%6d/%d ihave/sendme messages were processed\n", ihave_count, sendme_count X if ( ihave_count > 1 ) X { X for ( source in ihave_source ) X printf " %6d from %s\n", ihave_source[ source ], source X } X if ( sendme_count > 1 ) X { X for ( source in sendme_source ) X printf " %6d from %s\n", sendme_source[ source ], source X } X # X # Cancel and failed cancel reporting. These messages only appear X # in the log file if you are running Dave Aldens relaynews X # daemon. Since no cancel messages almost certianly means X # vanilla C news, we do not report on zero counts. X # X if ( cancel_count > 0 ) X { X printf " \n%6d articles were cancelled.\n", cancel_count X } X if ( precancel_count > 0 ) X { X printf " \n%6d articles were cancelled before receipt.\n", precancel_count X } X # X # Junkage report. Give total junkage, then break it down by X # reason. X # X printf "\n%6d articles were junked\n", junk_count X if ( junk_count > 0 ) X for ( group in junk_reason ) X printf " %6d %s\n", junk_reason[ group ], group X # X # Outgoing traffic report. Total ships, then break down by X # system. X # X printf( "\n%6d articles were shipped to other systems\n", ship_count ) X if ( ship_count > 0 ) X { X for ( to in ship_list ) X printf " %6d for %s\n", ship_list[ to ], to X printf " (Totals may differ due to same article shipped to multiple systems)\n" X } X # X # List how many articles we explictly rejected. Note we X # do not track the groups explicitly. X # X if ( x_count > 0 ) X { X printf "\n%6d articles were accepted but not posted/Xed by the active file\n", x_count X } X # X # Now we report on the questionable stuff X # X # X # This error comes first, as it indicates a severe problem X # with either you or your immediate neighbors X # X if ( no_msgid_count > 0 ) X { X printf "\n* * * Begin Serious Error! * * *\n" X printf "* * * There were attempts to insert articles which had *no* messages ids.\n" X printf "* * * This is a sign of significant errors in the posting or transfer\n" X printf "* * * software and should be checked out IMMEDIATELY!\n" X for ( source in no_msgid_source ) X printf "* * * %6d attempts were made from %s\n", no_msgid_source[ source ], source X printf "* * * End Serious Error! * * *\n" X } X # X # Other errors are less serious. X # X # The attempts to post to moderated groups. X # X printf "\n%6d articles were rejected as unapproved for moderated groups\n", unapproved_count X if ( unapproved_count > 0 ) X { X for ( target in unapproved_target ) X printf " %6d posted to %s\n", unapproved_target[ target ], target X for ( source in unapproved_source ) X printf " %6d came from %s\n", unapproved_source[ source ], source X } X # X # Now the transfer of unsubscribed stuff X # X printf "\n%6d articles were rejected as for unsubscribed groups\n", unsub_count X if ( unsub_count > 0 ) X { X for ( target in unsub_target ) X printf " %6d posted to %s\n", unsub_target[ target ], target X for ( source in unsub_source ) X printf " %6d came from %s\n", unsub_source[ source ], source X } X # X # List the articles rejected for having non-headers in the X # header section. Since the further spread of pedantic X # C news will eventually eliminate these, we do not report X # in the case where everything is OK. X # X if ( non_header_count > 0 ) X { X printf "\n%6d articles were rejected as having nonheaders in the header section\n", non_header_count X for ( source in non_header_source ) X printf " %6d came from %s\n", non_header_source[ source ], source X } X # X # List the number of articles rejected due to incorrect headers X # and where they came from. Since the further spread of pedantic X # C news will eventually eliminate these, we keep silent if X # everything is OK. X # X if ( bad_header_count > 0 ) X { X printf "\n%6d articles were rejected as having bad headers (no Date:, etc)\n", bad_header_count X for ( source in bad_header_source ) X printf " %6d came from %s\n", bad_header_source[ source ], source X } X # X # List those header fields and origins which were noted as X # being empty. Since the further spread of pedantic C news will X # eventually eliminate these, we keep silent if everything is OK. X # X if ( empty_header_count > 0 ) X { X printf "\n%6d articles were rejected as having empty headers\n", empty_header_count X for ( field in empty_header_field ) X printf " %6d entries had empty \"%s\" fields\n", empty_header_field[ field ], field X for ( source in empty_header_source ) X printf " %6d entries came from %s\n", empty_header_source[ source ], source X } X # X # Date rejections. Since the further spread of pedantic C news will X # eventually eliminate these, we keep silent if everything is OK. X # X if ( bad_date_count > 0 ) X { X printf "\n%6d articles were rejected as having unparseable dates:\n", bad_header_count X for ( source in bad_date_source ) X printf " %6d came from %s\n", bad_date_source[ source ], source X } X # X # These are article which are dated too far in the future. X # X if ( future_count > 0 ) X { X printf "\n%6d articles were rejected as dated too far in the future:\n", future_count X for ( source in future_source ) X printf " %6d came from %s\n", future_source[ source ], source X } X # X # Time rejects -- articles which are just too damned old. Probably X # signs of a news loop. X # X if ( oldies_count > 0 ) X { X printf "\n%6d articles were rejected as dated too far in the past:\n", oldies_count X for ( source in oldies_source ) X printf " %6d came from %s\n", oldies_source[ source ], source X } X # X # The fun stuff. This is where we report unrecognizable things. X # Data reported here is either meat for future mods to this script X # or indication of bugs in the news software. X # X if ( unknown_no_count > 0 ) X { X printf "\n%6d articles were rejected with an unrecognised comment\n", unknown_no_field X printf "about \"no such-and-such\" in the entry. Those rejections were:\n" X for ( no_field in unknown_no_field ) X printf " %s had the reason: %s\n", unknown_no_field[ no_field ], no_field X max_unknown = '$MAX_UNKNOWN' X printf "Here is up to %d of the entries:\n", max_unknown X for ( no_field in unknown_no_entry ) X if ( max_unknown-- > 0 ) X printf " %s\n", unknown_no_entry[ no_field ] X else X break X } X # X if ( nopath_count > 0 ) X { X printf "\n%6d articles were rejected with a missing Paths header.\n", nopath_count X max_nopath = '$MAX_NOPATH' X printf "Here are up to %d of the entries:\n", max_nopath X for ( nopath in nopath_entry ) X if ( max_nopath-- > 0 ) X printf " %s\n", nopath_entry X else X break X } X # X if ( mystery_dash_count > 0 ) X { X printf "\n%6d articles were rejected with an unrecognised \"-\" field.\n", mystery_dash_count X max_mystery_dash = '$MAX_MYSTERY_DASH' X printf "Here are up to %d of the entries:\n", max_mystery_dash X for ( mystery_dash in mystery_dash_entry ) X if ( max_mystery_dash-- > 0 ) X printf " %s\n", mystery_dash X else X break X } X if ( mystery_count > 0 ) X { X printf "\nThere were %d entries which were correctly formatted but with tag\n", mystery_count X printf "fields that were not recognized. Those tag fields and frequency were:\n" X tag_count = 0 X for ( mystery in mystery_tags ) X tag_count++ X for ( mystery in mystery_tags ) X { X if ( tag_count > 1 ) X printf " \"%s\" (%d),", mystery, mystery_tags[ mystery ] X else X printf " \"%s\" (%d)\n", mystery, mystery_tags[ mystery ] X tag_count-- X } X mystery_max='$MAX_MYSTERY' X printf "Here are up to %d of the entries:\n", mystery_max X for ( mystery in mystery_entry ) X if ( mystery_max-- > 0 ) X printf " %s\n", mystery X else X break X } X # X # Report on malformed lines in the log. Data reported here is X # almost certianly a bug in the news software. X # X defect_max = '$MAX_DEFECTS' X if ( defect_count > 0 ) X { X printf "\nThere were %d entries in the log with too few fields. Here is a sample:\n", defect_count X for ( defect in defective_entry ) X if ( defect_max-- > 0 ) X printf " \"%s\"\n", defect X else X break X } X } X # X # If nothing was wrong, print a nice reassuring message. X # X if ( ( mystery_count == 0 ) && ( mystery_dash_count == 0 ) && ( defect_count == 0 ) ) X printf "\nNo defects or unrecognized entries were found in the standard log.\n" X}' Xfi X/usr/ucb/Mail -s "News Log Report for $DATE" $NEWSMGR < $TEMPFILE END_OF_FILE if test 21554 -ne `wc -c <'cnews.logrep'`; then echo shar: \"'cnews.logrep'\" unpacked with wrong size! fi # end of 'cnews.logrep' fi echo shar: End of shell archive. exit 0 -- "If we don't provide support to our users someone is bound to confuse us with Microsoft." -- Charles "Chip" Yamasaki