Linux实践——编写who命令

Q1: who命令能做些什么?

$ who
xxx      :0            yyyy-mm-dd hh:mm (:0)
xxx      pts/0         yyyy-mm-dd hh:mm (:0)

这是在CentOS7上的输出结果,who的版本为8.22。每一行代表一个已经登陆的用户,第一列是用户名,第二列是终端名,第三列是登录时间。

可以通过阅读手册详细查看who命令。

$ man who

Q2: who命令是如何工作的?

首先我们先阅读联机帮助:

DESCRIPTION
       Print information about users who are currently logged in.
       If FILE is not specified, use /var/run/utmp.  /var/log/wtmp as FILE is common.  If ARG1 ARG2 given, -m presumed: ‘am i‘ or ‘mom likes‘ are usual.

通过描述得知已登录用户的信息一般会在/var/run/utmp或/var/log/wtmp中。

utmp文件中保存的是当前正在本系统中的用户的信息。wtmp文件中保存的是登录过本系统的用户的信息。

现在关注utmp文件,who通过读取该文件获得信息。使用带有-k命令可以根据关键字搜索联机帮助:

$ man -k utmp

注意观察描述,有一行包含可能有用的信息:

utmpx (5)            - login records

接着使用man查看联机帮助:

$ man 5 utmp

浏览手册,发现该文件结构定义在头文件<utmp.h>中,首先去/usr/include/目录下寻找:

$ find /usr/include/utmp.h
/usr/include/utmp.h

然后用more或者cat命令查看该文件:

$ more /usr/include/utmp.h

浏览发现该文件并不是声明原始数据结构的头文件:

/* Get system dependent values and data structures.  */
#include <bits/utmp.h>

接着再到下一层目录bits当中查看,这里注意在C源文件中不能include<bits/utmp.h>,仍然是include<utmp.h>。

$ more /usr/include/bits/utmp.h

通过浏览代码,获取到结构体:

/* The structure describing an entry in the user accounting database.  */
struct utmp
{
  short int ut_type;		/* Type of login.  */
  pid_t ut_pid;			/* Process ID of login process.  */
  char ut_line[UT_LINESIZE];	/* Devicename.  */
  char ut_id[4];		/* Inittab ID.  */
  char ut_user[UT_NAMESIZE];	/* Username.  */
  char ut_host[UT_HOSTSIZE];	/* Hostname for remote login.  */
  struct exit_status ut_exit;	/* Exit status of a process marked
				   as DEAD_PROCESS.  */
/* The ut_session and ut_tv fields must be the same size when compiled
   32- and 64-bit.  This allows data files and shared memory to be
   shared between 32- and 64-bit applications.  */
#ifdef __WORDSIZE_TIME64_COMPAT32
  int32_t ut_session;		/* Session ID, used for windowing.  */
  struct
  {
    int32_t tv_sec;		/* Seconds.  */
    int32_t tv_usec;		/* Microseconds.  */
  } ut_tv;			/* Time entry was made.  */
#else
  long int ut_session;		/* Session ID, used for windowing.  */
  struct timeval ut_tv;		/* Time entry was made.  */
#endif

  int32_t ut_addr_v6[4];	/* Internet address of remote host.  */
  char __unused[20];		/* Reserved for future use.  */
};

观察当中的变量,可以获取到who所使用的成员变量ut_type(who用来过滤空白而留下当前用户)、ut_line(显示设备名,即用户的终端)、ut_user(用户名)、ut_host(远程登录用户名,(:0)显示)、ut_time(时间)。

所以who命令其实是打开utmp文件,读取记录,显示记录,然后关闭utmp文件。

Q3: 如何编写who?

根据以上分析得知who命令按照打开文件,读取记录,显示记录,关闭文件的流程工作。打开文件用open,读取用read,显示printf,关闭close。其中printf就不用介绍了。另外三个具体如下:

open
目标
    打开一个文件
头文件
    #include <fcntl.h>
函数原型
    int fd = open(char *name, int how)
参数
    name  文件名
    how    O_RDONLY, O_WRONLY, O_RDWR
返回值
    -1       遇到错误
    int      成功返回
时间: 2024-10-16 23:06:20

Linux实践——编写who命令的相关文章

linux下的shell命令的编写,以及java如何调用linux的shell命令(java如何获取linux上的网卡的ip信息)

程序员都很懒,你懂的! 最近在开发中,需要用到服务器的ip和mac信息.但是服务器是架设在linux系统上的,对于多网口,在获取ip时就产生了很大的问题.下面是在windows系统上,java获取本地ip的方法.贴代码: package com.herman.test; import java.net.InetAddress; /** * @see 获取计算机ip * @author Herman.Xiong * @date 2014年5月16日 09:35:38 */ public class

linux实践之ELF文件分析

linux实践之ELF文件分析 下面开始elf文件的分析. 我们首先编写一个简单的C代码. 编译链接生成可执行文件. 首先,查看scn15elf.o文件的详细信息. 以16进制形式查看scn15elf.o文件. 查看scn15elf.o中各个段和符号表的信息. 各个段的详细信息如下. 符号表的信息如下: 使用readelf命令查看各个段的详细信息: 段表信息如下: 符号表信息如下: 下面让我们开始分析文件头吧! 由于我的虚拟机是32位的,我下面就主要以32位的系统进行分析,就不比较32位机和64

linux上编写运行 dotnet core api

安装 Ubuntu         dotnet core 跨平台已不再是梦,它带来的意义非凡,比如api接口可以在linux上编写及部署,也可以在windows上编写好,打包发布,然后copy到linux上部署.从官网下载最新版本, 然后装到虚拟机VMware中.如果是centeros,系统开启后,默认进入命令行模式,估计一部分同学,看到类似dos界面,有点恐慌,不急,在命令行中输入startx回车,进入到图形界面.无论是哪种系统,虚拟机上装的操作系统,在开机启动后,都有可能窗口不能自适应,也

Linux内核模块编写详解

内核编程常常看起来像是黑魔法,而在亚瑟 C 克拉克的眼中,它八成就是了.Linux内核和它的用户空间是大不相同的:抛开漫不经心,你必须小心翼翼,因为你编程中的一个bug就会影响到整个系统,本文给大家介绍linux内核模块编写,需要的朋友可以参考下 内核编程常常看起来像是黑魔法,而在亚瑟 C 克拉克的眼中,它八成就是了.Linux内核和它的用户空间是大不相同的:抛开漫不经心,你必须小心翼翼,因为你编程中的一个bug就会影响到整个系统.浮点运算做起来可不容易,堆栈固定而狭小,而你写的代码总是异步的,

显示器 Linux 性能 18 (一个命令行工具传递)

对于系统和网络管理员来说每天监控和调试Linux系统的性能问题是一项繁重的工作.在IT领域作为一名Linux系统的管理员工作5年后,我逐渐认识到监控和保持系统启动并执行是多么的不easy.基于此原因.我们已编写了最常使用的18个命令行工具列表,这些工具将有助于每一个Linux/Unix 系统管理员的工作.这些命令行工具能够在各种Linux系统下使用.能够用于监控和查找产生性能问题的解决办法.这个命令行工具列表提供了足够的工具.您能够挑选适用于您的监控场景的工具. 1.Top-Linux进程监控

Linux下的 ls 命令的简单实现

又到了期末的时候,Linux实践课的老师挺厚道,布置了算是一个入门的大作业:实现一个简单版本的ls命令.三个文件,先上传再说. ls2.c #include <stdio.h> #include "ls_header.h" int main(int argc, char **argv) { // 处理参数, lsLong是带有 -l 参数的, lsShort为没有-l参数的ls命令 int i; if (argc == 1) { /* ls . */ lsShort(&qu

Linux 脚本编写基础

1. Linux 脚本编写基础1.1 语法基本介绍1.1.1 开头程序必须以下面的行开始(必须放在文件的第一行):#!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序.在这个例子中我们使用/bin/sh来执行程序. 当编辑好脚本时,如果要执行该脚本,还必须使其可执行. 要使脚本可执行:编译 chmod +x filename 这样才能用./filename 来运行1.1.2 注释 在进行shell编程时,以#开头的句子表示注释,直到这一行的结束.我们真诚地建议您在程序中使用

Linux的经典shell命令整理

Linux的经典shell命令整理 1.删除0字节文件find -type f -size 0 -exec rm -rf {} \; 2.查看进程按内存从大到小排列ps -e -o “%C : %p : %z : %a”|sort -k5 -nr 3.按cpu利用率从大到小排列ps -e -o “%C : %p : %z : %a”|sort -nr 4.打印说cache里的URLgrep -r -a jpg /data/cache/* | strings | grep “http:” | aw

怎样编写支持命令行选项的程序

Linux下的程序,常常支持N多的命令行选项.那么,我们怎样编写支持命令行选项的程序呢. 以下给出两个演示样例. 演示样例1,简单的命令行选项. 以下的程序,支持4个选项, -i,-n,-s,-d 编译后,能够这样运行 (选项之间的顺序无所谓): ./a.out   -i  -n 100  -s hahaha  -d 好了,以下是代码. #include <stdio.h> #include <unistd.h> #include <stdlib.h> int enab