Linux---who命令學習


who命令

獲取正在登錄系統的用戶

 

使用Linux的who命令 

第一個參數book代表用戶名,第二個參數tty7代表終端名,第三個參數代表時間,第四個參數代表用戶的登錄地址。

 

閱讀手冊

使用命令讀手冊

$ man who

可以知道who這個命令從 /var/run/utmp 和 /var/log/wtmp 兩個文件中獲取數據,

 

再通過命令,查找關於 “utmp” 的信息

$ man -k utmp

-k的意思是根據關鍵字查找

$man 5 utmp

我們查詢到一些關於utmp結構體中的元素,比如ut_user用戶名字、ut_line用戶設備、ut_time登錄時間等。

 

who命令的工作流程

        打開utmp

   +---->  讀取記錄 ------   +

   |                   |

   +-------顯示記錄        |

      關閉utmp  <------ +

 

 

who命令的編寫---版本1

 1 #include <stdio.h>
 2 #include <utmp.h>
 3 #include <fcntl.h>
 4 #include <unistd.h>
 5 #include <time.h>
 6 
 7 void show_info(struct utmp *utbufp);
 8 int main()
 9 {
10     struct utmp current_record;
11     int utmp_fd;
12     int reclen = sizeof(current_record);    
13 
14     utmp_fd = open(UTMP_FILE,O_RDONLY);    
15     if(utmp_fd == -1)
16     return -1;
17 
18     while( read(utmp_fd, &current_record,reclen) == reclen )
19      show_info(&current_record);
20     
21     close(utmp_fd);
22     return 0;
23 }
24 
25 void show_info(struct utmp *utbufp)
26 {
27 
28     printf("%-8.8s",utbufp->ut_name);
29     printf(" ");
30     printf("%-8.8s",utbufp->ut_line);
31     printf(" ");
32     printf("%101d",utbufp->ut_time);
33     printf(" ");
34     printf("(%s)",utbufp->ut_host);
35     printf(" ");
36     printf("\n");
37 }

輸出結果:

 

問題:

1. 有部分數據不是真實用戶的。

2. 時間顯示不對。

 

解決方法:

1.第一個問題

繼續使用命令

$ man 5 utmp

看到 ut_type中 USER_PROCESS表示的是已經登錄的用戶 ,那么第一個問題就解決了。

 

2.第二個問題

使用命令

$ man -k time | grep transform

看到ctime,使用命令查看ctime的使用方法

$ man 3 ctime

使用這個函數將 timeval轉換成一個字符串並返回一個指針,那么第二個問題也解決了。

 

who命令的編寫---版本2

 1 #include <stdio.h>
 2 #include <utmp.h>
 3 #include <fcntl.h>
 4 #include <unistd.h>
 5 #include <time.h>
 6 
 7 void show_info(struct utmp *utbufp);
 8 void show_time(long timeval);
 9 int main()
10 {
11     struct utmp current_record;
12     int utmp_fd;
13     int reclen = sizeof(current_record);    
14 
15     utmp_fd = open(UTMP_FILE,O_RDONLY);    
16     if(utmp_fd == -1)
17     return -1;
18 
19     while( read(utmp_fd, &current_record,reclen) == reclen )
20      show_info(&current_record);
21     
22     close(utmp_fd);
23     return 0;
24 }
25 
26 void show_info(struct utmp *utbufp)
27 {
28     if(utbufp->ut_type != USER_PROCESS)
29     return;    
30 
31     printf("%-8.8s",utbufp->ut_name);
32     printf(" ");
33     printf("%-8.8s",utbufp->ut_line);
34     printf(" ");
35     show_time(utbufp->ut_time);
36     printf(" ");
37     printf("(%s)",utbufp->ut_host);
38     printf("\n");
39 }
40 
41 void show_time(long timeval)
42 {
43     char *cp;
44     
45     cp = ctime(&timeval);
46 
47     printf("%12.12s",cp+4);
48 
49 }

輸出結果:

這樣一個簡單的who命令就完成了。

 

------------------------------於2019/5/5更新---------------------

改良who命令

Linux---cp命令中,介紹了有關緩沖區和系統開銷的知識,因此,我們可以改良自己編寫的who命令。

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <utmp.h>

#define NRECS    16
#define NULLUT    ((struct utmp*)NULL)
#define UTSIZE  (sizeof(struct utmp))

static char utmpbuf[NRECS * UTSIZE];
static int num_recs;
static int cur_rec;
static int fd_utmp = -1;

struct utmp* utmp_next();
int utmp_reload();
int utmp_open(char *filename);
void utmp_close();



int utmp_open(char *filename)
{
    fd_utmp = open(filename , O_RDONLY);
    cur_rec =  0;
    num_recs = 0;
    return fd_utmp;
}    



struct utmp* utmp_next()
{
    struct utmp* recp;
    if(fd_utmp == -1)
    {
        return NULLUT;
    }
    if(cur_rec == num_recs && utmp_reload() == 0)
    {
        return NULLUT;
    }

    recp = (struct utmp*) &utmpbuf[cur_rec * UTSIZE];
    cur_rec++;
    return recp;
}

int utmp_reload()
{
    int aimt_read;
    aimt_read = read(fd_utmp, utmpbuf, NRECS * UTSIZE);
    num_recs = aimt_read / UTSIZE;
    cur_rec  = 0;
    return num_recs;

}    


void utmp_close()
{
    if(fd_utmp != -1)
    close(fd_utmp);
}

編寫一個增大緩沖區的庫,調用的次數減少到原來的1/16。這樣程序能夠在更短的時間內完成。

 1 #include <stdio.h>
 2 #include <utmp.h>
 3 #include <fcntl.h>
 4 #include <unistd.h>
 5 #include <time.h>
 6 #include <sys/types.h>
 7 #include <stdlib.h>
 8 
 9 void show_info(struct utmp *utbufp);
10 void show_time(long timeval);
11 
12 #define SHOWHOST
13 
14 int main()
15 {
16     struct utmp* utbufp , *utmp_next();
17     if( utmp_open(UTMP_FILE) == -1)
18     {
19         perror(UTMP_FILE);
20         exit(1);
21     }    
22 
23     while( (utbufp = utmp_next()) != ((struct utmp *)NULL))
24      show_info(utbufp);
25     
26     utmp_close();
27     return 0;
28 }
29 
30 void show_info(struct utmp *utbufp)
31 {
32     if(utbufp->ut_type != USER_PROCESS)
33     return;    
34 
35     printf("%-8.8s",utbufp->ut_name);
36     printf(" ");
37     printf("%-8.8s",utbufp->ut_line);
38     printf(" ");
39     show_time(utbufp->ut_time);
40     printf(" ");
41     printf("(%s)",utbufp->ut_host);
42     printf("\n");
43 }
44 
45 void show_time(long timeval)
46 {
47     char *cp;
48     
49     cp = ctime(&timeval);
50 
51     printf("%12.12s",cp+4);
52 
53 }

 

 

本篇筆記自拜讀《 Unix/Linux編程實踐教程》

我也推薦和我一樣的初學者去拜讀這本書,讓你對linux有可下手的地方。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM