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