/var/log/wtmp

  1. On lilina, you may run the command "last" to see the login/logout time of users.
  2. Where does Linux store the login/logout information? On lilina it is stored in "/var/log/wtmp".
  3. If you read the manpage of wtmp(5), you will see that this file consists of a sequence of utmp structures, declared as follows in <utmp.h>.
    struct utmp {
        short   ut_type;              /* Type of record */
        pid_t   ut_pid;               /* PID of login process */
        char    ut_line[UT_LINESIZE]; /* Device name of tty - "/dev/" */
        char    ut_id[4];             /* Terminal name suffix,
                                         or inittab(5) ID */
        char    ut_user[UT_NAMESIZE]; /* Username */
        char    ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or
                                         kernel version for run-level
                                         messages */
        struct  exit_status ut_exit;  /* Exit status of a process
                                         marked as DEAD_PROCESS; not
                                         used by Linux init(8) */
        /* 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. */
    
        int32_t ut_session;           /* Session ID (getsid(2)),
                                         used for windowing */
        struct {
            int32_t tv_sec;           /* Seconds */
            int32_t tv_usec;          /* Microseconds */
        } ut_tv;                      /* Time entry was made */
    
       int32_t ut_addr_v6[4];        /* Internet address of remote
                                         host; IPv4 address uses
                                         just ut_addr_v6[0] */
        char __unused[20];            /* Reserved for future use */
    };
  4. Let's write a short program to try to read the first 20 records from that binary file:
    #include <utmp.h>
    #include <cstdio>
    
    int main()
    {
        struct utmp record;
        char filename[] = "/var/log/wtmp";
        FILE* fp = fopen(filename, "rb");
        for (int i=0; i<20; ++i)
        {
            fread(&record, sizeof(record), 1, fp);
            printf("%d %d %d\t%s %s %s\n", record.ut_type,
                    record.ut_tv.tv_sec, record.ut_tv.tv_usec,
                    record.ut_line, record.ut_user, record.ut_host
                    );
        }
        fclose(fp);
        return 0;
    }
    
  5. The result is:
    7 1644979290 647293     pts/0 s107321003 10.106.28.231
    8 1644979313 817487     pts/0
    7 1644983433 917849     pts/0 s107321009 125.224.190.109
    8 1644986814 262347     pts/0
    7 1644987201 101239     pts/0 s107321009 125.224.190.109
    7 1644987270 195332     pts/1 s107321003 125.224.190.109
    8 1644987285 856689     pts/0
    8 1644987306 167576     pts/1
    7 1644987316 899115     pts/0 s107321003 125.224.190.109
    8 1644987513 299026     pts/0
    7 1644991143 925222     pts/0 klim 10.20.23.41
    8 1644992341 454004     pts/0
    7 1644993671 280435     pts/0 s109402026 10.56.21.248
    8 1644993871 176771     pts/0
    7 1644993952 426588     pts/0 s109402026 10.56.21.248
    8 1644993969 96972      pts/0
    7 1644994030 891541     pts/0 s109402026 10.56.21.248
    8 1644994066 162410     pts/0
    7 1644996365 950893     pts/0 s110321001 10.49.21.232
    8 1644996465 697674     pts/0
  6. With this example, the manpage is easier to understand.
  7. The first column, ut_type, has two possible values:
  8. The second column (ut_tv.tv_sec) and the third column (ut_tv.tv_usec) composed the time value: second + micro-second. Normally "second" is precise enough. (The output of "last" only shows "minute".)
  9. The fifth column (ut_user) is the login username.
  10. The sixth column (ut_host) is the hostname or IP address where the user connects from.
  11. The fourth column (ut_line) is a logical line assigned to a user when he/she logs in. You may observe that logout records do not store ut_user and ut_host, because that should be the same as the corresponding login records.
  12. Extend the given sample code so that it will print out all records in "/var/log/wtmp". The first 20 records should be the same as the output of the above sample code. The last records should be the login records of current online users. You may verify that with the output of the command "who". For example, the "tail" of the output is
    7 1645633307 622206     pts/1 s110321037 10.55.21.174
    7 1645634877 799763     pts/2 solomon 10.20.20.247
    7 1645635559 545162     pts/3 s110321017 10.55.21.64
    7 1645635820 843173     pts/5 s109321021 175.183.80.90
    and "who" shows
    s110321037 pts/1        2022-02-24 00:21 (10.55.21.174)
    s110321017 pts/3        2022-02-24 00:59 (10.55.21.64)
    s109321021 pts/5        2022-02-24 01:03 (175.183.80.90)
    solomon  pts/2        2022-02-24 00:47 (10.20.20.247)
    
  13. These users are still online, so you only see their login records (ut_type==7) but no corresponding logout records (ut_type==8).