系统管理员工具包监视用户的使用情况.docx
《系统管理员工具包监视用户的使用情况.docx》由会员分享,可在线阅读,更多相关《系统管理员工具包监视用户的使用情况.docx(15页珍藏版)》请在冰豆网上搜索。
系统管理员工具包监视用户的使用情况
系统管理工具包:
监视用户的使用情况
简介:
研究在各种不同的日志中记录UNIX®登录和其他系统活动的新方法,并利用这些信息来监视用户的使用情况。
从很多角度来看,这样做是非常有帮助的,可以用于进行退款报告,或者仅用于了解系统中个别用户的繁忙和活跃程度,以便在进行规划和分配资源的时候能够起到帮助作用。
关于本系列
典型的UNIX®管理员拥有一套经常用于辅助管理过程的关键实用工具、诀窍和系统。
存在各种用于简化不同过程的关键实用工具、命令行链和脚本。
其中一些工具来自于操作系统,而大部分的诀窍则来源于长期的经验积累和减轻系统管理员工作压力的要求。
本系列文章主要专注于最大限度地利用各种UNIX环境中可用的工具,包括简化异构环境中的管理任务的方法。
获取当前用户的信息
要获取当前使用UNIX系统的用户的列表,可以使用很多不同的方式。
其中最显而易见、且最直接的方式是使用who命令。
who命令可以返回一个列表,该列表中包括当前登录的用户、他们所连接到的终端、他们登录的日期,以及他们登录的主机名的IP地址(如果他们是远程用户的话)。
您可以参见下面清单1中给出的示例。
清单1.使用who命令,以返回当前登录用户的列表
$who
mcpts/2Sep1214:
29(sulaco.mcslp.pri)
mcbrownpts/3Sep1214:
37(nautilus.mcslp.pri)
在某些系统中,还可以使用-q命令行选项,以提供一种更快捷的格式,如清单2中所示。
清单2.带-q选项的who命令
$who-q
mcmcbrown
#users=2
这个输出与某些系统中提供的、另一个名为users的命令的输出很类似,后者仅输出用户的列表,而不对其进行计数(请参见清单3)。
清单3.users命令
$users
mcmcbrown
通常,您可以通过添加-a和-H命令行选项来查找更详细的信息。
-a选项包括所有来自/var/adm/utmpx文件的最新信息,该文件用于记录登录信息。
这个文件还可以记录其他事件,如启动的日期和时间,以及最近的运行级别更改。
在本文稍后的内容中,您将进一步地了解该文件中存储的相关信息。
-H选项用于为输出中的各列添加标题信息。
您可以参见清单4中给出的示例。
清单4.带-a和-H选项的who命令
$who-aH
NAMELINETIMEIDLEPIDCOMMENTS
.systembootSep1211:
35
.run-level3Sep1211:
3530S
zsmon.Sep1211:
353:
14215
LOGINconsoleSep1211:
350:
20221
LOGINconsoleSep1211:
350:
20510(:
0)
mc+pts/2Sep1214:
29.569(sulaco.mcslp.pri)
mcbrown+pts/3Sep1214:
370:
12675(nautilus.mcslp.pri)
通过开头的两行,您可以了解最近一次启动系统的时间,以及最近一次运行级别更改的日期和详细情况。
这里所显示的计算机正在运行Solaris,并且它使用zsmon守护进程来监视串行端口上的登录。
然后,您将拥有两个到控制台的、标记的登录,其中一个是活动用户的登录,而另一个则附加到X服务器(:
0表示X窗口系统的屏幕参考)。
最后的两行是使用安全Shell(SSH)的远程登录。
对于所有的活动进程,您都将获取一个进程ID,这意味着您可以在ps列表中通过ID来识别原始用户。
LINE列是用户所连接到的终端;控制台显然是该计算机的主键盘和监视器。
pts行指的是自动创建的、用以处理远程SSH连接的伪终端。
当然,了解谁正在使用本地计算机是一件很有趣的工作,但是对于网络中其他的计算机,情况又如何呢?
获取远程用户的信息
有两个后台服务可以提供远程用户的信息,它们分别是rusers和rwho,分别通过两个守护进程rusersd(通常称为in.rusersd)和rwhod(也称为in.rwhod)来实现。
这两个服务都依赖于远程过程调用(RemoteProcedureCall,RPC)协议,以便在整个网络的范围内共享信息。
以前一直认为,启用rwhod和rusersd是对网络资源的浪费,因为这两个守护进程在网络中不断地广播信息,从而占用了带宽。
在拥有大量主机的网络中,所生成的信息量可能是非常大的。
现在,与网络的传输速度相比,所生成的信息量相对较小。
rwhod和rusersd在所有的系统中都是不可用的,但是对于那些提供了相应工具的系统来说,使用这些工具可以很容易地获取您所想要的信息。
如果这些工具还没有运行,那么您需要启动in.rwhod和in.rusersd守护进程。
一旦这两个守护进程开始运行,您就可以使用各种各样的工具输出所有计算机的相关信息。
rwho工具是who工具的远程、支持网络的版本。
清单5给出了一个示例。
清单5.rwho工具
$rwho-a
mcsolaris-desktop:
consoleSep1211:
293:
41
mcsolaris-desktop:
pts/1Sep1211:
32:
06
mcultra3:
pts/2Sep1214:
29
mcbrownultra3:
pts/3Sep1214:
37:
37
M
rwhod工具发出广播信息,并且捕获来自其他主机的广播信息,在/var/spool/rwhod目录中对其进行整理。
rusers工具向网络上其他主机中的rusersd守护进程发送广播,以便返回当前登录的用户的信息,如清单6所示。
清单6.rusers工具
$rusers
Sendingbroadcastforrusersdprotocolversion3...
192.168.0.31mcmcbrown
solaris-desktop.mcmc
在rwhod守护进程开始运行之后,还可以使用另一个工具ruptime,该工具可以返回本地网络中所有运行rwhod的服务器的加载和正常运行时间信息。
清单7显示了一个示例。
对于确定多台计算机的状态,并且不希望逐个地对它们进行登录,这是一个非常合适的工具。
清单7.ruptime工具
$ruptime
solaris-desktopup3:
53,1user,load0.00,0.00,0.00
ultra3up3:
46,2users,load0.00,0.00,0.00
对于who和rwho来说,将当前连接到您的计算机的who信息记录到/var/adm/utmp文件中,而曾经登录(并已注销)的用户的历史信息则保存于wtmp计算机中。
所有这些文件都包含了大量的信息,但是这些文件都没有可用的直接格式。
让我们更深入地研究这些文件,并了解如何显示这些信息。
用户活动所使用的日志文件
有很多文件用于记录用户的登录和活动。
用于记录这种信息的文件主要包括下面三个:
∙utmp,这个文件记录了当前登录的用户的相关信息。
对于用户的每次登录,它都应该包含一条相应的记录。
∙wtmp,这个文件记录了用户进行的所有登录(和注销)。
在一个繁忙的系统中,这个文件是相当大的,因为对于每次登录,它都包含一条登录和一条注销记录。
这个文件还包含了一些系统相关的日志信息,如重新启动、关闭和日期更改。
∙lastlog,这个文件记录了每个用户最近一次登录的时间。
对于每个用户,这个文件仅包含一条记录。
在您了解了这些文件是何时、采用何种方式写入的之后,那么这些文件之间的关系就相当直观了。
基本顺序如下所示:
∙当用户登录的时候,打开lastlog文件,并对他们的记录中的登录日期和时间进行更新。
然后,打开utmp,并记录他们的当前登录信息。
将登录记录(通常将这些信息的副本添加到lastlog)写入到utmp日志中,以记录相应的登录信息。
∙在注销期间,删除写入到utmp的登录记录(因为该用户不再处于登录状态),但是将一条新记录写入到wtmp,以记录该用户已经注销的事实。
∙这些文件的格式都是二进制的;所以,必须使用一种单独的、能够读取和解析其中信息的工具来报告这些信息。
通常,wtmp和lastlog文件的基本格式是相同的,并且它们都使用一种简单格式来记录登录时间、登录行和主机名称行信息,如清单8中所示,其中显示了Solaris格式。
清单8.wtmp中的Solaris格式
structlastlog{
time_tll_time;
charll_line[UT_LINESIZE];
charll_host[UT_HOSTSIZE];
};
对于不同的操作系统,格式是不相同的,因此您必须非常小心地提取合适的信息。
在AIX®中,清单9显示了utmp定义。
清单9.utmp定义
structutmp
{
charut_user[8];
charut_id[14]
charut_line[12];
shortut_type;
pid_tut_pid;
structexit_status
{
shorte_termination;
shorte_exit;
}
清单10显示了记录的ut_type字段值的定义。
清单10.ut_type字段值的定义
#defineEMPTY0
#defineRUN_LVL1
#defineBOOT_TIME2
#defineOLD_TIME3
#defineNEW_TIME4
#defineINIT_PROCESS5
#defineLOGIN_PROCESS6
#defineUSER_PROCESS7
#defineDEAD_PROCESS8
#defineACCOUNTING9
#defineUTMAXTYPEACCOUNTING
因为是根据用户ID进行编码的,所以该记录中不包括用户名信息。
如果登录用户的ID是1000,那么可以通过访问位于1000xsizeof(structlastlog)的记录来定位对应的lastlog记录。
utmp文件结构与其非常类似,但因为它是关于登录、注销、以及其他事件条目的顺序日志,所以该记录包括清单11中的登录信息。
清单11.utmp文件结构定义
structutmp{
charut_line[UT_LINESIZE];
charut_name[UT_NAMESIZE];
charut_host[UT_HOSTSIZE];
time_tut_time;
};
Linux®ut_type具有类似的值定义,如清单12中所示。
清单12.Linuxut_type定义
#defineUT_UNKNOWN0
#defineRUN_LVL1
#defineBOOT_TIME2
#defineNEW_TIME3
#defineOLD_TIME4
#defineINIT_PROCESS5
#defineLOGIN_PROCESS6
#defineUSER_PROCESS7
#defineDEAD_PROCESS8
#defineACCOUNTING9
还有一种更加复杂的结构定义,如清单13中所示。
清单13.更加复杂的utmp结构定义
structutmp{
shortut_type;/*typeoflogin*/
pid_tut_pid;/*PIDofloginprocess*/
charut_line[UT_LINESIZE];/*devicenameoftty-"/dev/"*/
charut_id[4];/*initidorabbrev.ttyname*/
charut_user[UT_NAMESIZE];/*username*/
charut_host[UT_HOSTSIZE];/*hostnameforremotelogin*/
structexit_statusut_exit;/*Theexitstatusofaprocess
markedasDEAD_PROCESS*/
/*Theut_sessionandut_tvfieldsmustbethesamesizewhen
compiled32-and64-bit.Thisallowsdatafilesandshared
memorytobesharedbetween32-and64-bitapplications*/
#if__WORDSIZE==64&&defined__WORDSIZE_COMPAT32
int32_tut_session;/*SessionID,usedforwindowing*/
struct{
int32_ttv_sec;/*Seconds*/
int32_ttv_usec;/*Microseconds*/
}ut_tv;/*Timeentrywasmade*/
#else
longintut_session;/*SessionID,usedforwindowing*/
structtimevalut_tv;/*Timeentrywasmade*/
#endif
int32_tut_addr_v6[4];/*IPaddressofremotehost*/
char__unused[20];/*Reservedforfutureuse*/
};
大多数系统都提供了一些简单工具,以便为您提取相关的信息。
要转储wtmp文件的内容,可以使用last命令。
该命令将转储所有的信息(请参见清单14)。
清单14.使用last命令转储wtmp文件的内容
$last
statmonftpnautilus.mcslp.pWedSep1215:
50-15:
50(00:
00)
statmonftpnarcissus.mcslp.WedSep1215:
50-15:
50(00:
00)
statmonftpnostromo.mcslp.pWedSep1215:
50-15:
50(00:
00)
statmonftpsulaco.mcslp.priWedSep1215:
49-15:
49(00:
00)
statmonftpnautilus.mcslp.pWedSep1215:
45-15:
45(00:
00)
statmonftpnostromo.mcslp.pWedSep1215:
45-15:
45(00:
00)
statmonftpnarcissus.mcslp.WedSep1215:
45-15:
45(00:
00)
通常,如果需要的话,您可以通过用户、主机或者tty对信息进行筛选。
例如,要获取root所进行的所有登录,可以使用清单15中所示的内容。
清单15.获取root所进行的所有登录
$lastroot
rootconsole:
0MonSep2511:
32-11:
32(00:
00)
rootconsole:
0MonSep2511:
27-11:
27(00:
00)
rootconsoleSatSep913:
17-13:
28(00:
11)
rootconsoleSatSep910:
47-13:
14(02:
26)
rootconsoleSunSep306:
52-down(6+03:
54)
rootconsole:
0SatSep214:
24-down(16:
27)
rootconsoleSatSep208:
02-down(06:
13)
rootconsoleFriAug2517:
16-down(00:
39)
rootconsoleSunAug2016:
04-16:
04(00:
00)
rootconsoleThuJul2007:
23-07:
31(00:
07)
rootconsoleThuJul2007:
22-07:
23(00:
00)
rootconsoleThuJul2002:
57-02:
57(00:
00)
rootconsoleWedJul1912:
22-down(05:
38)
rootconsoleWedJul1912:
10-12:
19(00:
08)
rootconsole:
0WedJul1912:
05-12:
09(00:
04)
rootconsoleWedJul1911:
47-11:
55(00:
07)
wtmpbeginsWedJul1909:
54
因为wtmp还包含关于重新启动和关闭的信息,所以您也可以列出这些信息(请参见清单16)。
清单16.获取关于重新启动和关闭的信息
$lastreboot
rebootsystembootWedSep1211:
28
rebootsystemdownWedSep512:
16
rebootsystembootMonSep313:
03
rebootsystemdownThuMar111:
33
rebootsystembootThuMar109:
57
rebootsystemdownThuMar108:
12
rebootsystembootThuMar108:
05
rebootsystemdownThuMar108:
12
rebootsystembootThuMar108:
05
rebootsystemdownThuMar108:
03
rebootsystembootThuMar108:
02
rebootsystemdownSunDec1710:
04
rebootsystembootSunDec1710:
02
rebootsystemdownMonSep2511:
44
rebootsystembootMonSep2510:
2
前面介绍的这些工具都是十分有效的,但是如果您希望自己解析这些信息,那该怎么办呢?
您可以编写一个简单的C程序以提取相关信息,但事实上,您还可以通过使用Perl的unpack()函数来完成这个任务。
解析二进制日志文件
在Perl中使用unpack函数需要创建适当的packstring,它用于定义您希望从二进制记录数据(从原始二进制utmp文件中读取)中提取的数据类型。
清单17显示了一个很简单的Perl脚本,该脚本用于对wtmp中的数据进行直接转储。
清单17.转储wtmp中数据的Perl脚本
my$packstring="a8a8a8ssssl";
my$reclength=length(pack($packstring));
my@ut_types=qw(EMPTYRUN_LVLBOOT_TIMEOLD_TIME
NEW_TIMEINIT_PROCESSLOGIN_PROCESS
USER_PROCESSDEAD_PROCESSACCOUNTING);
open(D,"
";
while(sysread(D,my$rec,$reclength))
{
my($user,$userid,$line,$pid,$type,$eterm,$eexit,$time)
=unpack($packstring,$rec);
print("$user,$userid,$line,$pid,$ut_types[$type],",
"$eterm,$eexit,",scalarlocaltime($time),"\n");
}
close(D)ordie"Couldn'tclosewtmp,$!
";
请注意,您必须使用sysread来读取数据,因为您读取的是原始二进制包(而不是行)。
您所使用的packstring将获取用户名、用户ID、tty线路、PID、utmp类型、终端退出代码和时间。
最前面的三个字段是非常重要的,因为其中包含了行、名称和主机信息。
在utmp.h中,对这些字段的大小进行了合适的定义(请参见清单18)。
清单18.utmp.h中定义的最前面三个字段的大小
#defineUT_NAMESIZE8
#defineUT_LINESIZE8
#defineUT_HOSTSIZE16
请注意,您必须正确地获取数据的大小,因为它将影响到您所读取的信息。
如果您使用的是Solaris或者BSD系统,那么它使用了一种更加简单的结构(如清单8所示),因此,您需要使用一个不同的packstring和提取的字段,如清单19中所示。
清单19.Solaris或者BSD系统的数据转储
my$packstring="a8a8a16l";
my$reclength=length(pack($packstring));
my@ut_types=qw(EMPTYRUN_LVLBOOT_TIMEOLD_TIME
NEW_TIMEINIT_PROCESSLOGIN_PROCESS
USER_PROCESSDEAD_PROCESSACCOUNTING);
open(D,"