ac指令的简单实现
2015-09-14 22:19
330 查看
2015-09-14
ac指令通过分析/var/log/wtmp日志文件,统计登陆和退出记录,得出用户的连接时间。
1.第一步是读取wtmp文件
wtmp文件和utmp文件的记录格式是一样的,可以使用struct utmp结构体,将wtmp的记录逐条的都出来。
为了便于分析简单的将记录内容组织并输出如下:
2.通过分析wtmp的帮助文档(man 5 wtmp),简单得出如下论断:
1) 当ut_line为伪终端时,即上图所示device为pts/0的类似记录,其退出记录是ut_type为DEAD_PROCESS且ut_line相同的记录。如果没有该条记录,则应该将其退出记录记为之后最近的那次ut_user为shutdown的记录。
2) 当ut_line不是伪终端,即上图device为:0的记录,其退出记录是ut_type为DEAT_PROCESS且ut_line和ut_host相同的记录。如果没有该条记录,则应该将其退出记录记为之后最近的那次ut_user为shutdown的记录。
3) 对于ut_user为reboot的特殊记录,其退出记录是ut_user为shutdown的记录。
3.将开始记录和退出记录合并成计算连接时间的记录,然后将连接时间累加起来就能得出总的连接时间。
4.输出结果和系统的ac指令对比输出如下:
5.源代码
http://download.csdn.net/detail/qq123386926/9106479
ac指令通过分析/var/log/wtmp日志文件,统计登陆和退出记录,得出用户的连接时间。
1.第一步是读取wtmp文件
wtmp文件和utmp文件的记录格式是一样的,可以使用struct utmp结构体,将wtmp的记录逐条的都出来。
int travel_wtmp( st_link_node **stppLink ) { int fd = 0; int iRdNum = 0; int iEntSize = sizeof( struct utmp ); struct utmp stEntry; struct utmp stFix; st_link_node *stpCur = *stppLink; if( ( fd = open( WTMP_FILE, O_RDONLY ) ) < 0 ) { fprintf( stderr, "open error: %s\n", strerror( errno ) ); return -1; } while( ( iRdNum = read( fd, &stEntry, iEntSize ) ) == iEntSize ) { st_link_node *stpNode = NULL; if( stEntry.ut_type == DEAD_PROCESS || stEntry.ut_type == RUN_LVL ) { find_matched_process( *stppLink, &stEntry ); continue; } if( strcmp( stEntry.ut_user, BOOT_USER ) == 0 ) find_matched_process( *stppLink, &stEntry ); if( ( stpNode = malloc( sizeof( st_link_node ) ) ) == NULL ) { fprintf( stderr, "malloc error: %s\n", strerror( errno ) ); return -1; } init_node( stpNode ); memcpy( &( stpNode->data ), &stEntry, iEntSize ); if( stpCur == NULL ) *stppLink = stpNode; else stpCur->next = stpNode; stpCur = stpNode; } memset( &stFix, 0x00, sizeof( struct utmp ) ); stFix.ut_type = RUN_LVL; strcpy( stFix.ut_user, SHUT_USER ); stFix.ut_tv.tv_sec = time( NULL ); find_matched_process( *stppLink, &stFix ); if( iRdNum < 0 ) { fprintf( stderr, "read error: %s\n", strerror( errno ) ); return -1; } return 0; }
为了便于分析简单的将记录内容组织并输出如下:
2.通过分析wtmp的帮助文档(man 5 wtmp),简单得出如下论断:
1) 当ut_line为伪终端时,即上图所示device为pts/0的类似记录,其退出记录是ut_type为DEAD_PROCESS且ut_line相同的记录。如果没有该条记录,则应该将其退出记录记为之后最近的那次ut_user为shutdown的记录。
2) 当ut_line不是伪终端,即上图device为:0的记录,其退出记录是ut_type为DEAT_PROCESS且ut_line和ut_host相同的记录。如果没有该条记录,则应该将其退出记录记为之后最近的那次ut_user为shutdown的记录。
3) 对于ut_user为reboot的特殊记录,其退出记录是ut_user为shutdown的记录。
static int find_matched_process( st_link_node *stpLink, struct utmp *stpData ) { while( stpLink != NULL ) { if( stpLink->data.ut_type == USER_PROCESS && stpLink->iFlag != MATCHED ) { if( strcmp( stpLink->data.ut_line, NOUT_LINE ) == 0 ) { if( ( stpData->ut_type == DEAD_PROCESS && strcmp( stpData->ut_line, stpLink->data.ut_line ) == 0 && strcmp( stpData->ut_host, stpLink->data.ut_host ) == 0 ) || ( stpData->ut_type == RUN_LVL && strcmp( stpData->ut_user, SHUT_USER ) == 0 ) ) { memcpy( &( stpLink->endata ), stpData, sizeof( struct utmp ) ); stpLink->iFlag = MATCHED; } } else { /* pesu terminal */ if( ( stpData->ut_type == DEAD_PROCESS && strcmp( stpLink->data.ut_line, stpData->ut_line ) == 0 ) || ( stpData->ut_type == RUN_LVL && strcmp( stpData->ut_user, SHUT_USER ) == 0 ) ) { memcpy( &( stpLink->endata ), stpData, sizeof( struct utmp ) ); stpLink->iFlag = MATCHED; } } } else if( strcmp( stpLink->data.ut_user, BOOT_USER ) == 0 && stpLink->iFlag != MATCHED ) { if( stpData->ut_type == RUN_LVL && strcmp( stpData->ut_user, SHUT_USER ) == 0 ) { memcpy( &( stpLink->endata ), stpData, sizeof( struct utmp ) ); stpLink->iFlag = MATCHED; } } stpLink = stpLink->next; } return 0; }
3.将开始记录和退出记录合并成计算连接时间的记录,然后将连接时间累加起来就能得出总的连接时间。
typedef struct _link_node { struct utmp data; struct utmp endata; int iFlag; struct _link_node *next; } st_link_node;
4.输出结果和系统的ac指令对比输出如下:
5.源代码
http://download.csdn.net/detail/qq123386926/9106479
相关文章推荐
- 9.性能测试工具Locust的高级使用(二)
- Robolectric 配置
- 关掉mysql中sleep程序
- 【EF】 EF的一些错误和解决办法
- try...catch的使用
- mysql部署到云主机的笔记
- 杭电1173采矿
- LeetCode-Delete Node in a Linked List
- 产品经理的修炼之道
- Android Bluetooth4.0(BLE是Bluetooth Low Energy的简称) 官方API
- OpenGL 第三课 中文
- HDU 1559 最大子矩阵
- C++的STL进一步总结之map
- Nginx 日志格式剖析
- 海明校验码——如何求解
- 限制UITextView中的字数
- hdu 5438Ponds
- https://github.com/i66soft/osharp
- StyleCop默认的规 4000 则
- 洛谷1005 矩阵取数游戏(dp+高精)