last command of ubuntu to view system login information

Keywords: Linux Session Database ssh

Learn about last command and its data source under linux

last
Data sources: / var/log/wtmp (default record of login times and duration per user, etc.) and / var/log/btmp (details, including login failure requests)
Data source format: binary (read through dump-utmp command)
Last [-adRx][-f][-n] [Account Name...] [Terminal Number...]

Figure 1 last command format
Description of parameters:
- a Display the host name or IP address from where to log in to the system on the last line.
- d Converts IP addresses to host names.
- f < Record File > Specifies the record file. The default is to display the record of the wtmp file in the / var/log directory, but the content of the btmp in the / var/log directory is richer and can display remote logins, such as ssh login, including failed login requests.
- N < Number of Display Columns > or - < Number of Display Columns > Sets the number of display columns for listing.
- R does not display the host name or IP address of the logged-in system.
- x Displays information about system shutdown, reboot, and changes in execution level.
- i Displays the status of a specific ip login

- t. Display information before YYYYMMDDHMMSS

Example 1

last

Last Figure 2
Normal command restart is shown as down, while power forced restart is crash

Field Introduction:

Column 1: User name

Column 2: Terminal location

Column 3: Log on to the ip or the kernel

Column 4: Start time

Column 5: End time (still login in has not quit downward until normal shutdown crash until forced shutdown)

Column 6: Duration

Example 2

last -x

Figure 3 last-x

Example 3

 last  -n

Figure 4 Last-x-n

Example 4

last -f /var/log/btmp | head -100

Figure 5 Last-f/var/log/btmp | head-100

Example 5

 last -t  20130819090800

Display login information before 08-19 09:09:00, 2013

last Figure 6 -t  20130819090800

Deep Understanding - Promotion

structure

The utmp file holds the information of users currently in the system.
The information of the users who have logged on to the system is stored in the wtmp file.

/ The var/log/wtmp file structure, like the / var/run/utmp file structure, refers to struct utmp in / usr/include/bits/utmp.h.

     

/* The `struct utmp' type, describing entries in the utmp file.  GNU version.
   Copyright (C) 1993, 1996, 1997, 1998, 1999, 2002
   Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#ifndef _UTMP_H
# error "Never include <bits/utmp.h> directly; use <utmp.h> instead."
#endif

#include <paths.h>
#include <sys/time.h>
#include <sys/types.h>
#include <bits/wordsize.h>


#define UT_LINESIZE	32
#define UT_NAMESIZE	32
#define UT_HOSTSIZE	256


/* The structure describing an entry in the database of
   previous logins.  */
struct lastlog
  {
#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
    int32_t ll_time;
#else
    __time_t ll_time;
#endif
    char ll_line[UT_LINESIZE];
    char ll_host[UT_HOSTSIZE];
  };


/* The structure describing the status of a terminated process.  This
   type is used in `struct utmp' below.  */
struct exit_status
  {
    short int e_termination;	/* Process termination status.  */
    short int e_exit;		/* Process exit status.  */
  };


/* 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.  */
#if __WORDSIZE == 64 && defined __WORDSIZE_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.  */
};

/* Backwards compatibility hacks.  */
#define ut_name		ut_user
#ifndef _NO_UT_TIME
/* We have a problem here: `ut_time' is also used otherwise.  Define
   _NO_UT_TIME if the compiler complains.  */
# define ut_time	ut_tv.tv_sec
#endif
#define ut_xtime	ut_tv.tv_sec
#define ut_addr		ut_addr_v6[0]


/* Values for the `ut_type' field of a `struct utmp'.  */
#define EMPTY		0	/* No valid user accounting information.  */

#define RUN_LVL		1	/* The system's runlevel.  */
#define BOOT_TIME	2	/* Time of system boot.  */
#define NEW_TIME	3	/* Time after system clock changed.  */
#define OLD_TIME	4	/* Time when system clock changed.  */

#define INIT_PROCESS	5	/* Process spawned by the init process.  */
#define LOGIN_PROCESS	6	/* Session leader of a logged in user.  */
#define USER_PROCESS	7	/* Normal process.  */
#define DEAD_PROCESS	8	/* Terminated process.  */

#define ACCOUNTING	9

/* Old Linux name for the EMPTY type.  */
#define UT_UNKNOWN	EMPTY


/* Tell the user that we have a modern system with UT_HOST, UT_PID,
   UT_TYPE, UT_ID and UT_TV fields.  */
#define _HAVE_UT_TYPE	1
#define _HAVE_UT_PID	1
#define _HAVE_UT_ID	1
#define _HAVE_UT_TV	1
#define _HAVE_UT_HOST	1


The functions for reading and modifying these files are as follows (/usr/include/utmp.h):

/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#ifndef	_UTMP_H
#define	_UTMP_H	1

#include <features.h>

#include <sys/types.h>


__BEGIN_DECLS

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

/* Compatibility names for the strings of the canonical file names.  */
#define UTMP_FILE	_PATH_UTMP
#define UTMP_FILENAME	_PATH_UTMP
#define WTMP_FILE	_PATH_WTMP
#define WTMP_FILENAME	_PATH_WTMP



/* Make FD be the controlling terminal, stdin, stdout, and stderr;
   then close FD.  Returns 0 on success, nonzero on error.  */
extern int login_tty (int __fd) __THROW;


/* Write the given entry into utmp and wtmp.  */
extern void login (__const struct utmp *__entry) __THROW;

/* Write the utmp entry to say the user on UT_LINE has logged out.  */
extern int logout (__const char *__ut_line) __THROW;

/* Append to wtmp an entry for the current time and the given info.  */
extern void logwtmp (__const char *__ut_line, __const char *__ut_name,
		     __const char *__ut_host) __THROW;

/* Append entry UTMP to the wtmp-like file WTMP_FILE.  */
extern void updwtmp (__const char *__wtmp_file, __const struct utmp *__utmp)
     __THROW;

/* Change name of the utmp file to be examined.  */
extern int utmpname (__const char *__file) __THROW;

/* Read next entry from a utmp-like file.  */
extern struct utmp *getutent (void) __THROW;

/* Reset the input stream to the beginning of the file.  */
extern void setutent (void) __THROW;

/* Close the current open file.  */
extern void endutent (void) __THROW;

/* Search forward from the current point in the utmp file until the
   next entry with a ut_type matching ID->ut_type.  */
extern struct utmp *getutid (__const struct utmp *__id) __THROW;

/* Search forward from the current point in the utmp file until the
   next entry with a ut_line matching LINE->ut_line.  */
extern struct utmp *getutline (__const struct utmp *__line) __THROW;

/* Write out entry pointed to by UTMP_PTR into the utmp file.  */
extern struct utmp *pututline (__const struct utmp *__utmp_ptr) __THROW;


#ifdef	__USE_MISC
/* Reentrant versions of the file for handling utmp files.  */
extern int getutent_r (struct utmp *__buffer, struct utmp **__result) __THROW;

extern int getutid_r (__const struct utmp *__id, struct utmp *__buffer,
		      struct utmp **__result) __THROW;

extern int getutline_r (__const struct utmp *__line,
			struct utmp *__buffer, struct utmp **__result) __THROW;

#endif	/* Use misc.  */

__END_DECLS

#endif /* utmp.h  */

     

 

The utmpname() function sets the path of the utmp file, and the default path is macro_PATH_UTMP, which is defined in / usr/include/paths.h

#define _PATH_UTMP "/var/run/utmp"

The setutent() function opens the file utmp and points the file pointer to the beginning of the file.
The getutent() function reads a struct utmp structure from the file utmp at a time. Reading failure returns NULL.
The endutent() function closes the file utmp.
The pututline() function writes a struct utmp structure into the file utmp.

 

Following is a small program (mywho.c) that mimics the who command under Linux.

#include <stdio.h>

#include <stdlib.h>

#include <utmp.h>

#include <time.h>



int main()

{

        struct utmp *p_utent;

        long t;



        setutent(); /* rewinds the file pointer to the beginning of the utmp file */

        while((p_utent = getutent()) != NULL){

                if(p_utent->ut_type != USER_PROCESS) 

                        continue;

                printf("%s\t", p_utent->ut_user); 

                printf("%s\t", p_utent->ut_line); 

                t = p_utent->ut_tv.tv_sec;

                printf("%.20s\t", ctime(&t) + 4);

                printf("(%s)\n", p_utent->ut_host);



        }

        endutent(); /* closes the utmp file. */



        return 0;

}

Compile

gcc -o mywho mywho.c

Function

./mywho

Figure 7 mywho Running Results

 

Add the following statement in the above program to read the user information that has logged on to the system.

utmpname(_PATH_WTMP); /* #define _PATH_WTMP "/var/log/wtmp" */

#include <stdio.h>

#include <stdlib.h>

#include <utmp.h>

#include <time.h>



int main()

{

        struct utmp *p_utent;

        long t;



        utmpname(_PATH_WTMP); /* #define _PATH_WTMP "/var/log/wtmp" */



        setutent(); /* rewinds the file pointer to the beginning of the utmp file */

        while((p_utent = getutent()) != NULL){

                if(p_utent->ut_type != USER_PROCESS) 

                        continue;

                printf("%s\t", p_utent->ut_user); 

                printf("%s\t", p_utent->ut_line); 

                t = p_utent->ut_tv.tv_sec;

                printf("%.20s\t", ctime(&t) + 4);

                printf("(%s)\n", p_utent->ut_host);



        }

        endutent(); /* closes the utmp file. */



        return 0;

}


 

Compile

gcc -o mywho mywho.c

Function

./mywho

Figure 8 mywho Running Results (So User Login Information)

The functions above are non-thread-safe and non-reentrant because they store the returned results in a static variable and can be overridden by the same calls later.
The corresponding reentrant version is as follows (/usr/include/utmp.h):

#define _GNU_SOURCE /* or _SVID_SOURCE or _BSD_SOURCE */

#include <utmp.h>



int getutent_r(struct utmp *ubuf, struct utmp **ubufp);
int getutid_r(struct utmp *ut, struct utmp *ubuf, struct utmp **ubufp);
int getutline_r(struct utmp *ut, struct utmp *ubuf, struct utmp **ubufp);

Posted by ScubaDvr2 on Sun, 30 Jun 2019 18:01:53 -0700