Created
December 3, 2016 00:18
-
-
Save dreness/8fc259ad45db0a190addcc73e50dc5ac to your computer and use it in GitHub Desktop.
Properly sort the sa(8) accounting records by time stamp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
from __future__ import print_function | |
from datetime import datetime | |
''' | |
Display the account records gathered by the sa(8) facility. | |
from /usr/include/sys/acct.h | |
or on macOS, /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/sys/acct.h | |
/* | |
* Accounting structures; these use a comp_t type which is a 3 bits base 8 | |
* exponent, 13 bit fraction ``floating point'' number. Units are 1/AHZ | |
* seconds. | |
*/ | |
typedef u_int16_t comp_t; | |
struct acct { | |
char ac_comm[10]; /* command name */ | |
comp_t ac_utime; /* user time */ | |
comp_t ac_stime; /* system time */ | |
comp_t ac_etime; /* elapsed time */ | |
u_int32_t ac_btime; /* starting time */ | |
uid_t ac_uid; /* user id */ | |
gid_t ac_gid; /* group id */ | |
u_int16_t ac_mem; /* average memory usage */ | |
comp_t ac_io; /* count of IO blocks */ | |
dev_t ac_tty; /* controlling tty */ | |
#define AFORK 0x01 /* fork'd but not exec'd */ | |
#define ASU 0x02 /* used super-user permissions */ | |
#define ACOMPAT 0x04 /* used compatibility mode */ | |
#define ACORE 0x08 /* dumped core */ | |
#define AXSIG 0x10 /* killed by a signal */ | |
u_int8_t ac_flag; /* accounting flags */ | |
}; | |
''' | |
def chunks(l, n): | |
"""Yield successive n-sized chunks from l.""" | |
for i in xrange(0, len(l), n): | |
yield l[i:i + n] | |
def flipHex(i): | |
return int("".join(i)[::-1].encode("hex"), 16) | |
fh = open("/var/account/acct", 'r') | |
sa = fh.read() | |
tfmt = "%Y-%m-%d %H:%M:%S" | |
pfmt = "{: <20} {: <5} {: <5} {}" | |
print(pfmt.format("Start Time", "uid", "gid", "command")) | |
records = [] | |
# entries from the acct file are each 40 chars long | |
for rec in chunks(sa, 40): | |
r = {} | |
r['cmd'] = rec[:9] | |
r['start_time'] = flipHex(rec[16:20]) | |
r['uid'] = flipHex(rec[20:24]) | |
r['gid'] = flipHex(rec[24:28]) | |
records.append(r) | |
sorted_records = sorted(records, key=lambda k: k['start_time']) | |
for r in sorted_records: | |
print(pfmt.format(str(datetime.fromtimestamp(r['start_time'])), r['uid'], r['gid'], r['cmd'])) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment