HYPERLINK.docx
- 文档编号:11770321
- 上传时间:2023-04-01
- 格式:DOCX
- 页数:9
- 大小:35.22KB
HYPERLINK.docx
《HYPERLINK.docx》由会员分享,可在线阅读,更多相关《HYPERLINK.docx(9页珍藏版)》请在冰豆网上搜索。
HYPERLINK
华夏35度
DataMining
编写who命令--从Linux中学习Linux
执行who命令查看已登录的用户信息
$who
orisuntty72011-12-1914:
12(:
0)
orisunpts/02011-12-1914:
12(:
0.0)
显示出了:
用户名、终端名、登录时间、登录地址
现在我们要自己写一个程序来实现who。
是不是要用到一些特殊的系统调用,或者需要root权限呢?
实际上都不用,我们要学会使用Linux的联机帮助文档,从Linux中学习Linux。
要学习linux系统给我们提供的编程接口,很多时间查看相应的头文件就可以了。
$manwho
WHO
(1)UserCommandsWHO
(1)
NAME
who-showwhoisloggedon
SYNOPSIS
who[OPTION]...[FILE|ARG1ARG2]
DESCRIPTION
Printinformationaboutuserswhoarecurrentlyloggedin.
-a,--all
sameas-b-d--login-p-r-t-T-u
-b,--boot
timeoflastsystemboot
-d,--dead
……
注意我红色标出的那个1是小节编号。
使用who命令时可以指定FILE,在who的DESCRIPTION中有这么几行字:
IfFILEisnotspecified,use/var/run/utmp./var/log/wtmpasFILEiscommon.实际上who是通过读取/var/run/utmp文件来获取已登录的用户信息的。
带有选项-k的man命令可以根据关键字来搜索联机帮助。
$man-kutmp
endutent(3)-accessutmpfileentries
endutxent(3)-accessutmpfileentries
getutent(3)-accessutmpfileentries
getutent_r(3)-accessutmpfileentries
getutid(3)-accessutmpfileentries
getutid_r(3)-accessutmpfileentries
getutline(3)-accessutmpfileentries
getutline_r(3)-accessutmpfileentries
getutmp(3)-copyutmpstructuretoutmpx,andviceversa
getutmpx(3)-copyutmpstructuretoutmpx,andviceversa
getutxent(3)-accessutmpfileentries
getutxid(3)-accessutmpfileentries
getutxline(3)-accessutmpfileentries
login(3)-writeutmpandwtmpentries
logout(3)-writeutmpandwtmpentries
pututline(3)-accessutmpfileentries
pututxline(3)-accessutmpfileentries
sessreg
(1)-manageutmp/wtmpentriesfornon-initclients
setutent(3)-accessutmpfileentries
setutxent(3)-accessutmpfileentries
utmp(5)-loginrecords
utmpname(3)-accessutmpfileentries
utmpx(5)-loginrecords
utmpxname(3)-accessutmpfileentries
这里的“5”是小节编号。
$man5utmp
UTMP(5)LinuxProgrammer'sManualUTMP(5)
NAME
utmp,wtmp-loginrecords
SYNOPSIS
#include
DESCRIPTION
Theutmpfileallowsonetodiscoverinformationaboutwhoiscurrentlyusingthesystem.Theremaybemoreusers currentlyusingthesystem,becausenotallprogramsuseutmplogging.
……
/*Valuesforut_typefield,below*/
#defineEMPTY0/*Recorddoesnotcontainvalidinfo (formerlyknownasUT_UNKNOWNonLinux)*/
#defineRUN_LVL1/*Changeinsystemrun-level(see init(8))*/
#defineBOOT_TIME2/*Timeofsystemboot(inut_tv)*/
#defineNEW_TIME3/*Timeaftersystemclockchange (inut_tv)*/
#defineOLD_TIME4/*Timebeforesystemclockchange (inut_tv)*/
#defineINIT_PROCESS5/*Processspawnedbyinit(8)*/
#defineLOGIN_PROCESS6/*Sessionleaderprocessforuserlogin*/
#defineUSER_PROCESS7/*Normalprocess*/
#defineDEAD_PROCESS8/*Terminatedprocess*/
#defineACCOUNTING9/*Notimplemented*/
#defineUT_LINESIZE32
#defineUT_NAMESIZE32
#defineUT_HOSTSIZE256
structexit_status{/*Typeforut_exit,below*/
shortinte_termination;/*Processterminationstatus*/
shortinte_exit;/*Processexitstatus*/
};
structutmp{
shortut_type;/*Typeofrecord*/
pid_tut_pid;/*PIDofloginprocess*/
charut_line[UT_LINESIZE];/*Devicenameoftty-"/dev/"*/
charut_id[4];/*Terminalnamesuffix, orinittab(5)ID*/
charut_user[UT_NAMESIZE];/*Username*/
charut_host[UT_HOSTSIZE];/*Hostnameforremotelogin,or kernelversionforrun-level messages*/
structexit_statusut_exit;/*Exitstatusofaprocess markedasDEAD_PROCESS;not usedbyLinuxinit(8)*/
/*Theut_sessionandut_tvfieldsmustbethesamesizewhen compiled32-and64-bit.Thisallowsdatafilesandshared memorytobesharedbetween32-and64-bitapplications.*/
#if__WORDSIZE==64&&defined__WORDSIZE_COMPAT32
int32_tut_session;/*SessionID(getsid
(2)), usedforwindowing*/
struct{
int32_ttv_sec;/*Seconds*/
int32_ttv_usec;/*Microseconds*/
}ut_tv;/*Timeentrywasmade*/
#else
longut_session;/*SessionID*/
structtimevalut_tv;/*Timeentrywasmade*/
#endif
int32_tut_addr_v6[4];/*Internetaddressofremote host;IPv4addressuses justut_addr_v6[0]*/
char__unused[20];/*Reservedforfutureuse*/
};
/*Backwardscompatibilityhacks*/
#defineut_nameut_user
#ifndef_NO_UT_TIME
#defineut_timeut_tv.tv_sec
#endif
#defineut_xtimeut_tv.tv_sec
#defineut_addrut_addr_v6[0]
……
#include
#include
#include
#include
#defineSHOWHOST
voidshow_info(structutmp*);
intmain(){
structutmprecord;
FILE*fp;
intstrulen=sizeof(record);
if((fp=fopen("/var/run/utmp","r"))==0){//打开文件
perror("fopen");
exit(0);
}
memset(&record,0x00,strulen);
while(fread(&record,strulen,1,fp)){//循环读取记录(结构体)
show_info(&record);
}
fclose(fp);//关闭文件
return0;
}
voidshow_info(structutmp*buf){
printf("%-8s",buf->ut_name);//输出用户名
printf("%-8s",buf->ut_line);//终端设备名
printf("%10ld",buf->ut_time);//登录时间
#ifdefSHOWHOST
printf("(%s)",buf->ut_host);
#endif
printf("\n");
}
运行结果:
$./who1
reboot~1324275122(2.6.38-13-generic)
runlevel~1324275122(2.6.38-13-generic)
LOGINtty41324275122()
LOGINtty51324275122()
LOGINtty21324275122()
LOGINtty31324275122()
LOGINtty61324275122()
LOGINtty11324275128()
orisuntty71324275138(:
0)
orisunpts/01324275175(:
0.0)
orisunpts/11324285820(:
0.0)
上面的程序有两个问题:
1.时间显示的是time_t类型的,不便于阅读
2.utmp文件不仅包含活动用户的信息,连那些尚未用到的终端信息也保存在utmp文件。
解决问题1。
让我们找一下和时间格式转换相关的函数。
$man-ktime|grep-itransform
asctime(3)-transformdateandtimetobroken-downtimeorASCII
asctime_r(3)-transformdateandtimetobroken-downtimeorASCII
ctime(3)-transformdateandtimetobroken-downtimeorASCII
ctime_r(3)-transformdateandtimetobroken-downtimeorASCII
gmtime(3)-transformdateandtimetobroken-downtimeorASCII
gmtime_r(3)-transformdateandtimetobroken-downtimeorASCII
localtime(3)-transformdateandtimetobroken-downtimeorASCII
localtime_r(3)-transformdateandtimetobroken-downtimeorASCII
mktime(3)-transformdateandtimetobroken-downtimeorASCII
好,我们仔细阅读一下localtime
$manlocaltime
CTIME(3)LinuxProgrammer'sManualCTIME(3)
NAME
asctime,ctime,gmtime,localtime,mktime,asctime_r,ctime_r,gmtime_r,localtime_r-transformdateandtimeto
broken-downtimeorASCII
SYNOPSIS
#include
char*asctime(conststructtm*tm);
char*asctime_r(conststructtm*tm,char*buf);
char*ctime(consttime_t*timep);
char*ctime_r(consttime_t*timep,char*buf);
structtm*gmtime(consttime_t*timep);
structtm*gmtime_r(consttime_t*timep,structtm*result);
structtm*localtime(consttime_t*timep);
structtm*localtime_r(consttime_t*timep,structtm*result);
time_tmktime(structtm*tm);
FeatureTestMacroRequirementsforglibc(seefeature_test_macros(7)):
asctime_r(),ctime_r(),gmtime_r(),localtime_r():
_POSIX_C_SOURCE>=1||_XOPEN_SOURCE||_BSD_SOURCE||_SVID_SOURCE||_POSIX_SOURCE
DESCRIPTION
Thectime(),gmtime()andlocaltime()functionsalltakeanargumentofdatatypetime_twhichrepresentscalendar
time.Wheninterpretedasanabsolutetimevalue,itrepresentsthenumberofsecondselapsedsincetheEpoch,
1970-01-0100:
00:
00+0000(UTC).
Theasctime()andmktime()functionsbothtakeanargumentrepresentingbroken-downtimewhichisarepresentation
separatedintoyear,month,day,etc.
Broken-downtimeisstoredinthestructuretmwhichisdefinedin
structtm{
inttm_sec;/*seconds*/
inttm_min;/*minutes*/
inttm_hour;/*hours*/
inttm_mday;/*dayofthemonth*/
inttm_mon;/*month*/
inttm_year;/*year*/
inttm_wday;/*dayoftheweek*/
inttm_yday;/*dayintheyear*/
解决问题2。
通过阅读utmp.h我们发现,utmp结构中有一个成员ut_type,当它的值为7(USER_PROCESS)时,表示这个用户已经登录。
综上所述,我们给出改进后的代码。
#include
#include
#include
#include
#include
#defineSHOWHOST
voidshow_info(structutmp*);
intmain(){
structutmprecord;
FILE*fp;
intstrulen=sizeof(record);
if((fp=fopen("/var/run/utmp","r"))==0){//打开文件
perror("fopen");
exit(0);
}
memset(&record,0x00,strulen);
while(fread(&record,strulen,1,fp)){//循环读取记录(结构体)
show_info(&record);
}
fclose(fp);//关闭文件
return0;
}
voidshow_info(structutmp*buf){
if(buf->ut_type!
=USER_PROCESS)//非登录用户
return;
printf("%-8s",buf->ut_name);//输出用户名
printf("%-12s",buf->ut_line);//终端设备名
time_ttimelong=buf->ut_time;
structtm*localnow=localtime(&timelong);
printf("%d-%d-%d%d:
%d",localnow->tm_year+1990,localnow->tm_mon+1,localnow->tm_mday,localnow->tm_hour,localnow->tm_min);//登录时间
#ifdefSHOWHOST
printf("(%s)",buf->ut_host);
#endif
printf("\n");
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- HYPERLINK