|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
有些人号称用过十几种甚至几十种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)LinuxProgrammersManualUTMP(5)
NAME
utmp,wtmp-loginrecords
SYNOPSIS
#include<utmp.h>
DESCRIPTION
Theutmpfileallowsonetodiscoverinformationaboutwhoiscurrentlyusingthesystem.Theremaybemoreuserscurrentlyusingthesystem,becausenotallprogramsuseutmplogging.
……
/*Valuesforut_typefield,below*/
#defineEMPTY0/*Recorddoesnotcontainvalidinfo(formerlyknownasUT_UNKNOWNonLinux)*/
#defineRUN_LVL1/*Changeinsystemrun-level(seeinit(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,orkernelversionforrun-levelmessages*/
structexit_statusut_exit;/*ExitstatusofaprocessmarkedasDEAD_PROCESS;notusedbyLinuxinit(8)*/
/*Theut_sessionandut_tvfieldsmustbethesamesizewhencompiled32-and64-bit.Thisallowsdatafilesandsharedmemorytobesharedbetween32-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];/*Internetaddressofremotehost;IPv4addressusesjustut_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<stdio.h>#include<utmp.h>#include<string.h>#include<stdlib.h>#defineSHOWHOSTvoidshow_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);//登录工夫#ifdefSHOWHOSTprintf("(%s)",buf->ut_host);#endifprintf("
- ");}
复制代码 运转了局:$./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)
下面的程序有两个成绩:
- 工夫显现的是time_t范例的,方便于浏览
- 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)LinuxProgrammersManualCTIME(3)
NAME
asctime,ctime,gmtime,localtime,mktime,asctime_r,ctime_r,gmtime_r,localtime_r-transformdateandtimeto
broken-downtimeorASCII
SYNOPSIS
#include<time.h>
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<time.h>asfollows:
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<stdio.h>
#include<utmp.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#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("
");
}
<br>
在linux中学习命令的最好办法是学习Shell脚本编程,Shell脚本比起其他语言来学习简单,但是功能却十分强大.通过学习Shell编程,能让你掌握大量的linux命令。 |
|