who命令能做些什么
功能
who命令可以查看谁正在使用系统。
每一行代表一个已登录的用户
第一列代表用户名
第二列代表终端名
第三列代表登录时间
第四列(括号里面的)代表登录地址
(有些版本默认不显示第四列的内容)
命令参数
-a ——–显示所有用户
-b ——–最近一次系统启动的时间
-d ——–显示已退出的进程
-H ——–显示表头
-l ———只显示系统登录进程
–ips ——应显示用户名的地方显示IP地址(两个’ - ‘)
–lookup -尝试通过DNS对用户名排序(两个’ - ‘)
-m ——–与命令”who am i”相同1
-q ———只显示登录系统的用户名和用户个数
-r ———显示当前运行等级
–help —–显示帮助信息
–version -显示版本信息
who命令是如何工作的
原理
who命令通过读取utmp文件来获取已登录用户的信息,已登录用户的信息存放在/var/run/utmp中(不同的系统发行版中存放路径可能有所不同)。
utmp文件中保存的是结构体数组,数组元素的类型是utmp类型的结构,可以在utmp.h中找到utmp类型的定义
struct utmp {
char ut_user[32]; //user login name
char ut_id[14];
char ut_line[32]; //device name
short ut_type;
pid_t ut_pid;
struct exit_status {
short e_termination;
short e_exit;
}
time_t ut_time; //time entry was made
char ut_host[64]; //host name
}
utmp结构体一共包含8个成员变量,其中与who命令有关的有ut_user保存用户名,ut_line保存设备名, ut_time保存登录时间,ut_host保存用户用于登录的远程计算机名
如何编写who命令
流程图
示例代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<utmp.h>
#include<fcntl.h>
#include<time.h>
#define SHOWHOST
void showtime(long );
void show_info(struct utmp *);
int main(int argc, char *argv[ ])
{
if(argc == 3)
struct utmp utbuf;
int utmpfd;
if( (utmpfd = open(UTMP_FILE,O_RDONLY)) == -1) {
perror(UTMP_FILE);
exit(1);
}
while( ( read(utmpfd, &utbuf, sizeof(utbuf)) ) == sizeof(utbuf) ) {
show_info(&utbuf);
}
close(utmpfd);
return 0;
}
void show_info(struct utmp *utbufp)
{
if( utbufp->ut_type != USER_PROCESS) {
return;
}
printf("%-8.8s",utbufp->ut_name); //用户名
printf(" ");
printf("%-8.8s", utbufp->ut_line); //设备名
printf(" ");
showtime(utbufp->ut_time); //登录时间
#ifdef SHOWHOST
if(utbufp->ut_host[0] != '\0') {
printf("(%s)",utbufp->ut_host); //用户的主机名
}
#endif
printf("\n");
}
void showtime(long timeval) //按指定格式显示时间
{
char *cp;
cp = ctime(&timeval);
printf("%12.12s", cp+4); //对 %12.12s 和 cp+4 有疑惑请参考timeval结构体
}
扩展
who am i 和 whoami
who am i 和 whoami 是不同的命令
who am i 命令显示当前用户的信息
whoami 命令只显示当前用户的用户名
(上面的代码不支持 whoami 命令和 who am i命令)
- 命令”who am i”可以查看当前有效用户的用户名 ↩