Linux编程实践——代码实现ac命令
2011-10-24 13:37
501 查看
ac命令是什么?
man ac命令后的解释是‘打印用户连接时间的统计数据’。
附带的两个常用的命令参数:
-d 日统计
-p 每个用户的统计
ac命令运行结果
进入命令行,依次敲下命令,输出结果比较了然:
$ ac
total 312.64
$ ac -d
Oct 8 total 48.11
Oct 9 total 74.71
Oct 12 total 86.85
Oct 14 total 58.57
Today total 44.82
$ ac -p
lizh 313.09
total 313.09
统计结果单位为小时。
要统计出这些系统信息,需要查询那些文档呢?那么把我们的问题列出个清单来对症下药即可:
ac的登陆时间和注销时间日志记录在哪个文件?
何时会写入登陆和注销日志记录?
日志记录的格式是什么?
统计时间的算法是什么?
姑且只有这些问题吧,由此查阅我们需要的文档。
我们需要什么?
首先要做的是分析实现过程,我们需要以下工具作为参考:
ac文档手册:man ac;
wtmp文档手册:man 5 wtmp;
dump-utmp工具查看wtmp;
login(3):写utmp和wtmp入口;
logout(3):写utmp和wtmp入口;
编程我们借助《Unix\Linux编程实践教程》acc.c
对于当前用户的登陆时间计算,是采用执行acc时取当前时间然后与登陆时间做差的方法。
该程序只是一定程度上实现了ac工具,并不完美:
为了便于编程,整理后的数据结构数组个数,用的宏RECORDSIZE直接定义;
带参数执行未实现,像-p、-d参数,可在目前程序基础上再做扩展;
用户更改系统时间时对执行结果的影响,未作作相应处理。
man ac命令后的解释是‘打印用户连接时间的统计数据’。
附带的两个常用的命令参数:
-d 日统计
-p 每个用户的统计
ac命令运行结果
进入命令行,依次敲下命令,输出结果比较了然:
$ ac
total 312.64
$ ac -d
Oct 8 total 48.11
Oct 9 total 74.71
Oct 12 total 86.85
Oct 14 total 58.57
Today total 44.82
$ ac -p
lizh 313.09
total 313.09
统计结果单位为小时。
要统计出这些系统信息,需要查询那些文档呢?那么把我们的问题列出个清单来对症下药即可:
ac的登陆时间和注销时间日志记录在哪个文件?
何时会写入登陆和注销日志记录?
日志记录的格式是什么?
统计时间的算法是什么?
姑且只有这些问题吧,由此查阅我们需要的文档。
我们需要什么?
首先要做的是分析实现过程,我们需要以下工具作为参考:
ac文档手册:man ac;
wtmp文档手册:man 5 wtmp;
dump-utmp工具查看wtmp;
login(3):写utmp和wtmp入口;
logout(3):写utmp和wtmp入口;
编程我们借助《Unix\Linux编程实践教程》acc.c
#include <stdio.h> #include <assert.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <time.h> #include "utmplib.c" #define RECORDSIZE 256 struct utmp_record{ short ut_type; //type char ut_user[UT_NAMESIZE]; // user name char ut_line[UT_LINESIZE]; //tty int32_t login_sec; //登陆时间 int32_t logout_sec; //注销时间 double diff; //登陆时间与注销时间的时间差 }; struct utmp_record record[RECORDSIZE]; int num_rd = 0; //整理日志后的记录数量 void show_wtmp(struct utmp*); //打印wtmp内容 void showtime(long); //打印时间(按照时间格式) void show_sorted(); void show_totaltime(); //打印总连接时间 double sec2hour(double ); //秒换算成小时 int main(int ac, char* av[]){ int wtmpfd; struct utmp* utbuf=utmp_next(); int i; if(utmp_open(WTMP_FILE) == -1){ perror(WTMP_FILE); return -1; } memset(&record[0],0,sizeof(struct utmp_record)*RECORDSIZE); while((utbuf=utmp_next()) != ((struct utmp*)NULL)) { // show_wtmp(utbuf); if((utbuf->ut_type == USER_PROCESS)) { for(i=0; i < num_rd; i++) { if( (strcmp(record[i].ut_user,utbuf->ut_user)==0)&& (record[i].login_sec == utbuf->ut_time)) { break; } } if(i == num_rd) { record[num_rd].ut_type = utbuf->ut_type; memcpy(record[num_rd].ut_user,utbuf->ut_user,UT_NAMESIZE); memcpy(record[num_rd].ut_line,utbuf->ut_line,UT_LINESIZE); record[num_rd].login_sec = utbuf->ut_time; num_rd++; } } else if(utbuf->ut_type == DEAD_PROCESS){ for(i=0; i < num_rd; i++){ if(record[i].ut_type == USER_PROCESS && strcmp(record[i].ut_line,utbuf->ut_line)==0 && utbuf->ut_time > record[i].login_sec) { record[i].logout_sec = utbuf->ut_time; record[i].ut_type = DEAD_PROCESS; record[i].diff = difftime(record[i].logout_sec,record[i].login_sec);//计算时间差 } } } else if((utbuf->ut_type == RUN_LVL && strncmp(utbuf->ut_user,"shutdown",8)==0) || (utbuf->ut_type == BOOT_TIME && strncmp(utbuf->ut_user,"reboot",6)==0)){ for(i=0; i < num_rd; i++){ if(record[i].ut_type == USER_PROCESS && utbuf->ut_time > record[i].login_sec ){ record[i].logout_sec = utbuf->ut_time; record[i].ut_type = utbuf->ut_type; record[i].diff = difftime(record[i].logout_sec, record[i].login_sec); } } } } // show_sorted(); utmp_close(); if(ac == 1 ){ //不带参数的ac令命 show_totaltime(); } else if (ac == 2){ //..带参数的ac命令,例如: //ac -p 按照用户名统计 //ac -d 按照日期统计 } return 0; } /* * show info() * displays the contents of the utmp struct * in human readable form1 * * displays nothing if record has no user name */ void show_wtmp( struct utmp *utbufp) { // if ( utbufp->ut_type != USER_PROCESS ) // return; printf("%-8.8s", utbufp->ut_name); /* the logname */ printf(""); /* a space */ printf("|%-8.8s", utbufp->ut_line); /* the tty */ printf(""); /* a space */ printf("|%d", utbufp->ut_type); printf(""); showtime( utbufp->ut_time ); /* display time */ #ifdef SHOWHOST if ( utbufp->ut_host[0] != '\0' ) printf(" (%s)", utbufp->ut_host);/* the host */ #endif printf("\n"); /* newline */ } void show_sorted(){ int i = 0; for(i=0; i < num_rd; i++){ printf("%-8.8s",record[i].ut_name); printf(""); printf("|%-8.8s",record[i].ut_line); printf("|%d",record[i].ut_type); printf(""); printf("%d",record[i].login_sec); printf(""); showtime(record[i].login_sec); printf(""); printf("%d",record[i].logout_sec); printf(""); showtime(record[i].logout_sec); printf(""); printf("|%f",record[i].diff); printf("\n"); } } void show_totaltime() { int i=0; double total =0.0; time_t now_t = time(NULL); for(i=0; i < num_rd;i++){ if(record[i].ut_type != USER_PROCESS){ total += record[i].diff; } else { record[i].diff = difftime(now_t,record[i].login_sec); total += record[i].diff; } } printf(" total %.2f\n",sec2hour(total)); } void showtime( long timeval ) /* * displays time in a format fit for human consumption * uses ctime to build a string then picks parts out of it * Note: %12.12s prints a string 12 chars wide and LIMITS * it to 12chars. */ { char *cp; /* to hold address of time */ cp = ctime(&timeval); /* convert time to string */ /* string looks like */ /* Mon Feb 4 00:46:40 EST 1991 */ /* 0123456789012345. */ printf("|%15.15s",cp+4 ); /* pick 12 chars from pos 4 */ } double sec2hour(double secs){ double hours = (secs/60.0/60.0); return hours; }
对于当前用户的登陆时间计算,是采用执行acc时取当前时间然后与登陆时间做差的方法。
该程序只是一定程度上实现了ac工具,并不完美:
为了便于编程,整理后的数据结构数组个数,用的宏RECORDSIZE直接定义;
带参数执行未实现,像-p、-d参数,可在目前程序基础上再做扩展;
用户更改系统时间时对执行结果的影响,未作作相应处理。
相关文章推荐
- linux编程实践1(实现pwd命令)
- linux编程实践3(实现who命令)
- linux编程实践:实现pwd命令
- linux编程实践4(实现ls -l命令)
- linux编程实践2(实现more命令)
- Linux&C编程之Linux系统命令“ls -l”的简单实现
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程 )(转)
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程)
- linux下使用系统调用编程实现dir命令功能
- 使用linux-c编程实现简单的ls命令
- Linux进程间通信(IPC)编程实践(十一)System V信号量---实现一个先进先出的共享内存shmfifo
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程)
- FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程 )
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程 )
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程 )
- Linux下模拟ping命令的C代码实现
- _FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程)
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程 )
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程 )
- [转]__FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程)