1#!/sbin/sh 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License, Version 1.0 only 7# (the "License"). You may not use this file except in compliance 8# with the License. 9# 10# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11# or http://www.opensolaris.org/os/licensing. 12# See the License for the specific language governing permissions 13# and limitations under the License. 14# 15# When distributing Covered Code, include this CDDL HEADER in each 16# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17# If applicable, add the following below this CDDL HEADER, with the 18# fields enclosed by brackets "[]" replaced with your own identifying 19# information: Portions Copyright [yyyy] [name of copyright owner] 20# 21# CDDL HEADER END 22# 23# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T 24# All Rights Reserved 25# Copyright 2003 Sun Microsystems, Inc. All rights reserved. 26# Use is subject to license terms. 27 28 29#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.9 */ 30# "nitely accounting shell, should be run from cron (adm) at 4am" 31# "does process, connect, disk, and fee accounting" 32# "prepares command summaries" 33# "shell is restartable and provides reasonable diagnostics" 34_adm=/var/adm 35_nite=/var/adm/acct/nite 36_sum=/var/adm/acct/sum 37_wtmpx=/var/adm/wtmpx 38PATH=/usr/lib/acct:/usr/bin:/usr/sbin 39export PATH 40_statefile=${_nite}/statefile 41_active=${_nite}/active 42_lastdate=${_nite}/lastdate 43_date="`date +%m%d`" 44_errormsg="\n\n************ ACCT ERRORS : see ${_active}${_date}********\n\n" 45_MIN_BLKS=500 46 47cd ${_adm} 48# "make sure that 2 crons weren't started, or leftover problems" 49date > ${_nite}/lock1 50chmod 400 ${_nite}/lock1 51ln ${_nite}/lock1 ${_nite}/lock 52if test $? -ne 0; then 53 _lnkerr="\n\n*********** 2 CRONS or ACCT PROBLEMS***********\n\n\n" 54 (date ; echo "$_lnkerr" ) | logger -p daemon.err 55 echo "$_lnkerr" | mailx adm root 56 echo "ERROR: locks found, run aborted" >> ${_active} 57 rm -f ${_nite}/lock* 58 exit 1 59fi 60 61# Check to see if there is enough space in /var/adm to do nitely accounting 62# 63_blocks=`df $_adm | sed 's/.*://' | awk '{ print $1 }'` 64if [ "$_blocks" -le $_MIN_BLKS ];then 65 echo "runacct: Insufficient space in $_adm ($_blocks blks); \c" 66 echo "Terminating procedure" 67 ( echo "runacct: Insufficient space in $_adm ($_blocks blks); \c" 68 echo "Terminating procedure" ) > /tmp/accounting_tmpfile 69 cat /tmp/accounting_tmpfile >> ${_active} 70 cat /tmp/accounting_tmpfile | logger -p daemon.err 71 mailx root adm < /tmp/accounting_tmpfile 72 rm /tmp/accounting_tmpfile 73 74 rm -f ${_nite}/lock* 75 exit 1 76fi 77 78 79case $# in 800) 81# "as called by the cron each day" 82 if test ! -r ${_lastdate} ; then 83 echo "0000" > ${_lastdate} 84 fi 85 if test "${_date}" = "`cat ${_lastdate}`"; then 86 (date; echo "${_errormsg}") | logger -p daemon.err 87 echo "${_errormsg}" | mailx root adm 88 echo "ERROR: acctg already run for `date`: check ${_lastdate}" >> ${_active} 89 rm -f ${_nite}/lock* 90 mv ${_active} ${_active}${_date} 91 exit 1 92 fi 93 echo ${_date} > ${_lastdate} 94 echo "SETUP" > ${_statefile} 95 nulladm ${_active} 96 echo ${_date} > ${_active} # debuging 97 echo "\n\n\n\n\n********** SYSTEM ACCOUNTING STARTED `date` **********\n\n\n\n\n" | logger -p daemon.notice 98 echo ${_date} > ${_active} # debuging 99 ;; 100 1011) 102# "runacct MMDD (date) will restart at current state" 103 _date=$1 104 _errormsg="\n\n************ ACCT ERRORS : see ${_active}${_date}********\n\n" 105 echo "restarting acctg for ${_date} at `cat ${_statefile}`" >> ${_active} 106 echo "\n\n\n\n\n********** SYSTEM ACCOUNTING RESTARTED `date` **********\n\n\n\n\n" | logger -p daemon.notice 107 ;; 108 1092) 110# "runacct MMDD STATE restart at specified state" 111 _date=$1 112 _errormsg="\n\n************ ACCT ERRORS : see ${_active}${_date}********\n\n" 113 echo "restarting acctg for ${_date} at $2" >> ${_active} 114 echo "previous state was `cat ${_statefile}`" >> ${_active} 115 echo "$2" > ${_statefile} 116 echo "\n\n\n\n\n********** SYSTEM ACCOUNTING RESTARTED `date` **********\n\n\n\n\n" | logger -p daemon.notice 117 ;; 118*) 119 (date; echo "${_errormsg}") | logger -p daemon.err 120 echo "${_errormsg}" | mailx root adm 121 echo "ERROR: runacct called with invalid arguments" > ${_active} 122 rm -f ${_nite}/lock* 123 mv ${_active} ${_active}${_date} 124 exit 1 125 ;; 126esac 127 128 129# "processing is broken down into seperate, restartable states" 130# "the statefile is updated at the end of each state so that the" 131# "next loop through the while statement switches to the next state" 132while [ 1 ] 133do 134case "`cat ${_statefile}`" in 135SETUP) 136 137cd ${_adm} 138 139(date ; ls -l fee pacct* ${_wtmpx}* ) >> ${_active} 140 141# "switch current pacct file" 142turnacct switch 143_rc=$? 144if test ${_rc} -ne 0; then 145 (date ; echo "${_errormsg}" ) | logger -p daemon.err 146 echo "${_errormsg}" | mailx root adm 147 echo "ERROR: turnacct switch returned rc=${_rc}" >> ${_active} 148 rm -f ${_nite}/lock* 149 mv ${_active} ${_active}${_date} 150 exit 1 151fi 152 153# " give pacct files unique names for easy restart " 154for _i in pacct?* 155do 156 if [ "${_i}" = "pacct?*" ] 157 then 158 rm -f ${_nite}/lock* 159 mv ${_active} ${_active}${_date} 160 exit 1 161 fi 162 if test -r S${_i}.${_date} ; then 163 (date ; echo "${_errormsg}" ) | logger -p daemon.err 164 echo "${_errormsg}" | mailx root adm 165 echo "ERROR: S${_i}.${_date} already exists" >> ${_active} 166 echo "file setups probably already run" >> ${_active} 167 rm -f ${_nite}/lock* 168 mv ${_active} ${_active}${_date} 169 exit 1 170 fi 171 mv ${_i} S${_i}.${_date} 172done 173 174 175# "add current time on end" 176if test -r ${_nite}/wtmpx.${_date} ; then 177 (date ; echo "${_errormsg}" ) | logger -p daemon.err 178 echo "${_errormsg}" | mailx root adm 179 echo "ERROR: ${_nite}/wtmpx.${_date} already exists: run setup manually" > ${_active} 180 rm -f ${_nite}/lock* 181 mv ${_active} ${_active}${_date} 182 exit 1 183fi 184closewtmp # fudge a DEAD_PROCESS for /var/wtmpx 185cp ${_wtmpx} ${_nite}/${_date}.wtmpx 186acctwtmp "runacct" ${_nite}/${_date}.wtmpx 187nulladm ${_wtmpx} 188utmp2wtmp # fudge active user from utmpx to wtmpx 189 190echo "files setups complete" >> ${_active} 191echo "WTMPFIX" > ${_statefile} 192;; 193 194WTMPFIX) 195# "verify the integrity of the wtmpx file" 196# "wtmpfix will automatically fix date changes" 197cd ${_nite} 198nulladm tmpwtmp wtmperror 199wtmpfix < ${_date}.wtmpx > tmpwtmp 2>wtmperror 200if test $? -ne 0 ; then 201 (date ; echo "${_errormsg}") | mailx root adm 202 echo "${_errormsg}" | logger -p daemon.err 203 echo "ERROR: wtmpfix errors see ${_nite}/wtmperror${_date}" >> ${_active} 204 rm -f ${_nite}/lock* 205 mv ${_active} ${_active}${_date} 206 mv wtmperror wtmperror${_date} 207 exit 1 208fi 209 210echo "wtmpx processing complete" >> ${_active} 211echo "CONNECT" > ${_statefile} 212;; 213 214 215CONNECT) 216# "produce connect records" 217# "the lineuse and reboots files are used by prdaily" 218cd ${_nite} 219nulladm lineuse reboots log ctacct.${_date} 220acctcon -l lineuse -o reboots < tmpwtmp 2> log > ctacct.${_date} 221 222# if the following test is true, then pnpsplit complained about 223# the year and holidays not being up to date. This used to be 224# a fatal error, but now it will continue to process the accounting. 225# 226if test -s log ; then 227 (date ; cat ${_nite}/log) | mailx adm root 228 echo "${_errormsg}" | logger -p daemon.err 229 cat ${_nite}/log >> ${_active}${_date} 230fi 231 232echo "connect acctg complete" >> ${_active} 233echo "PROCESS" > ${_statefile} 234;; 235 236 237PROCESS) 238# "correlate Spacct and ptacct files by number" 239# "will not process Spacct file if corresponding ptacct exists" 240# "remove the ptacct file to rurun the Spacct file" 241# "if death occurs here, rerunacct should remove last ptacct file" 242 243cd ${_nite} 244for _Spacct in ${_adm}/Spacct*.${_date} 245do 246 _ptacct=`basename ${_Spacct} | sed 's/Sp/pt/'` 247 if test -s ${_ptacct}; then 248 echo "WARNING: accounting already run for ${_Spacct}" \ 249 >> ${_active} 250 echo "WARNING: remove ${_nite}/${_ptacct} to rerun" \ 251 >> ${_active} 252 else 253 nulladm ${_ptacct} 254 acctprc < ${_Spacct} > ${_ptacct} 255 256 echo "process acctg complete for ${_Spacct}" >> ${_active} 257 fi 258done 259echo "all process actg complete for ${_date}" >> ${_active} 260echo "MERGE" > ${_statefile} 261;; 262 263 264MERGE) 265cd ${_nite} 266# "merge ctacct and ptacct files together" 267acctmerg ptacct*.${_date} < ctacct.${_date} > daytacct 268 269echo "tacct merge to create daytacct complete" >> ${_active} 270echo "FEES" > ${_statefile} 271;; 272 273 274FEES) 275cd ${_nite} 276# "merge in fees" 277if test -s ${_adm}/fee; then 278 cp daytacct tmpdayt 279 sort +0n +2 ${_adm}/fee | acctmerg -i | acctmerg tmpdayt > daytacct 280 echo "merged fees" >> ${_active} 281 rm -f tmpdayt 282else 283 echo "no fees" >> ${_active} 284fi 285echo "DISK" > ${_statefile} 286;; 287 288 289DISK) 290cd ${_nite} 291# "the last act of any disk acct procedure should be to mv its" 292# "entire output file to disktacct, where it will be picked up" 293if test -r disktacct; then 294 cp daytacct tmpdayt 295 acctmerg disktacct < tmpdayt > daytacct 296 echo "merged disk records" >> ${_active} 297 rm -f tmpdayt 298 mv disktacct /tmp/disktacct.${_date} 299else 300 echo "no disk records" >> ${_active} 301fi 302echo "MERGETACCT" > ${_statefile} 303;; 304 305MERGETACCT) 306cd ${_adm}/acct 307# "save each days tacct file in sum/tacct.${_date}" 308# "if sum/tacct gets corrupted or lost, could recreate easily" 309# "the monthly acctg procedure should remove all sum/tacct files" 310cp nite/daytacct sum/tacct${_date} 311if test ! -r sum/tacct; then 312 echo "WARNING: recreating ${_adm}/sum/tacct " >> ${_active} 313 nulladm sum/tacct 314fi 315 316# "merge in todays tacct with the summary tacct" 317rm -f sum/tacctprev 318cp sum/tacct sum/tacctprev 319acctmerg sum/tacctprev < sum/tacct${_date} > sum/tacct 320 321echo "updated sum/tacct" >> ${_active} 322echo "CMS" > ${_statefile} 323;; 324 325 326CMS) 327cd ${_adm}/acct 328# "do command summaries" 329nulladm sum/daycms 330if test ! -r sum/cms; then 331 nulladm sum/cms 332 echo "WARNING: recreating ${_adm}/sum/cms " >> ${_active} 333fi 334cp sum/cms sum/cmsprev 335acctcms ${_adm}/Spacct*.${_date} > sum/daycms 336acctcms -s sum/daycms sum/cmsprev > sum/cms 337acctcms -a -s sum/daycms | sed -n 1,56p > nite/daycms 338acctcms -a -s sum/cms | sed -n 1,56p > nite/cms 339lastlogin 340echo "command summaries complete" >> ${_active} 341echo "USEREXIT" > ${_statefile} 342;; 343 344 345USEREXIT) 346# "any installation dependant accounting programs should be run here" 347[ -s /usr/lib/acct/runacct.local ] && /usr/lib/acct/runacct.local 348 349echo "CLEANUP" > ${_statefile} 350;; 351 352 353CLEANUP) 354cd ${_adm}/acct 355# " finally clear files; could be done next morning if desired" 356nulladm ${_adm}/fee 357rm -f ${_adm}/Spacct*.${_date} 358# "put reports onto a file" 359prdaily >> sum/rprt${_date}; 360rm -f nite/lock* 361rm -f nite/ptacct*.${_date} nite/ctacct.${_date} 362mv -f nite/${_date}.wtmpx nite/owtmpx 363rm -f nite/wtmperror${_date} nite/active${_date} nite/tmpwtmp 364echo "system accounting completed at `date`" >> ${_active} 365echo "********** SYSTEM ACCOUNTING COMPLETED `date` **********" | logger -p daemon.notice 366echo "COMPLETE" > ${_statefile} 367exit 0 368;; 369 370*) 371 (date;echo "${_errormsg}") | logger -p daemon.err 372 echo "${_errormsg}" | mailx adm root 373 echo "ERROR: invalid state, check ${_statefile}" >> active 374 rm -f ${_nite}/lock* 375 mv ${_active} ${_active}${_date} 376 exit 1 377 ;; 378esac 379done 380 381 382# " runacct is normally called with no arguments from the cron" 383# " it checks its own locks to make sure that 2 crons or previous" 384# " problems have not occured" 385 386# " runacct uses the statefile to record its progress" 387# " each state updates the statefile upon completion" 388# " then the next loop though the while picks up the new state" 389 390# " to restart this shell, check the active file for diagnostics" 391# " fix up any corrupted data (ie. bad pacct or wtmpx files)" 392# " if runacct detected the error it removes the locks" 393# " remove the locks if necessary, otherwise runacct will complain" 394# " the lastdate file should be removed or changed" 395# " restart runacct at current state with: runacct MMDD" 396# " to override the statefile: runacct MMDD STATE" 397 398 399# " if runacct has been executed after the latest failure" 400# " ie. it ran ok today but failed yesterday" 401# " the statefile will not be correct" 402# " check the active files and restart properly" 403 404# " if runacct failed in the PROCESS state, remove the last" 405# " ptacct file because it may not be complete" 406 407# " if shell has failed several days, do SETUP manually" 408# " then rerun runacct once for each day failed" 409# " could use fwtmp here to split up wtmpx file correctly" 410 411# " normally not a good idea to restart the SETUP state" 412# " should be done manually, or just cleanup first" 413 414 415# " FILE USAGE: all files in /var/adm/acct/nite unless specified" 416 417# " statefile records progess of runacct" 418# " lastdate last day runacct ran in date +%m%d format" 419# " lock lock1 controls serial use of runacct" 420# " active place for all descriptive and error messages" 421# " fd2log fd2 output for runacct ( see cron entry ) " 422# " MMDD.wtmpx owtmpx yesterdays wtmpx file" 423# " tmpwtmp yesterdays wtmp corrected by wtmpfix" 424# " wtmperror place for wtmpfix error messages" 425# " lineuse lineusage report used in prdaily" 426# " reboots reboots report used in prdaily" 427# " log place for error messages from acctcon1" 428# " ctacct.MMDD connect tacct records for MMDD" 429# " ptacct.n.MMDD process tacct records n files for MMDD" 430# " daytacct total tacct records for this days accounting" 431# " disktacct disk tacct records produced by disk shell" 432# " daycms ascii daily command summary used by prdaily" 433# " cms acsii total command summary used by prdaily" 434 435# " following files in /var/adm directory" 436 437# " fee output from chargefee program" 438# " pacct active pacct file" 439# " pacctn switched pacct files" 440# " Spacctn.MMDD pacct files for MMDD after SETUP state" 441# " wtmpx active wtmpx file" 442 443# " following files in /var/adm/acct/sum" 444 445# " loginlog output of lastlogin used in prdaily" 446# " tacct total tacct file for current fiscal" 447# " tacct.MMDD tacct file for day MMDD" 448# " cms total cms file for current fiscal" 449# " rprt.MMDD output of prdaily program" 450# " MMDD.wtmpx saved copy of wtmpx for MMDD" 451# " pacct.MMDD concatenated version of all pacct files for MMDD" 452# " cmsprev total cms file without latest update" 453# " tacctprev total tacct file without latest update" 454# " daycms cms files for todays usage" 455