0

If I connect via SSH to my Debian 12 Server from another Linux Server and run the who -m command, it displays the following:

test-user    pts/1        2024-01-24 11:13 (xx.xx.xx.xx)

But, if I connect from a Windows 11 computer, via Windows Terminal or using a third-party App to connect to the same Debian 12 Server using the same exact user and run the same who -m command, the date/time format display is different.

test-user    pts/0        Jan 24 11:15 (xx.xx.xx.xx)

I am running this line in the /etc/profile to determine the IP address from the user on every login, but it doesn't work properly as the output is different and those spaces are altering the outcome.

myip=$(who -m | awk '{print substr($5, 2, length($5) - 2)}')

Is there a way to control the date/time output for the who command? What could be causing this behavior?

Update

Running the locale command from:

From Linux:

$locale

LANG=en_US.UTF-8 LANGUAGE= LC_CTYPE="en_US.UTF-8" LC_NUMERIC="en_US.UTF-8" LC_TIME="en_US.UTF-8" LC_COLLATE="en_US.UTF-8" LC_MONETARY="en_US.UTF-8" LC_MESSAGES="en_US.UTF-8" LC_PAPER="en_US.UTF-8" LC_NAME="en_US.UTF-8" LC_ADDRESS="en_US.UTF-8" LC_TELEPHONE="en_US.UTF-8" LC_MEASUREMENT="en_US.UTF-8" LC_IDENTIFICATION="en_US.UTF-8" LC_ALL=

From Windows 11

$locale

LANG= LANGUAGE= LC_CTYPE="POSIX" LC_NUMERIC="POSIX" LC_TIME="POSIX" LC_COLLATE="POSIX" LC_MONETARY="POSIX" LC_MESSAGES="POSIX" LC_PAPER="POSIX" LC_NAME="POSIX" LC_ADDRESS="POSIX" LC_TELEPHONE="POSIX" LC_MEASUREMENT="POSIX" LC_IDENTIFICATION="POSIX" LC_ALL=

Just to note that this behavior doesn't seem to happen with all the Linux Servers I connect to. It varies and it's explained in the solution below.

As I understood the root cause as per the explanation below, I opted to use the suggestions and they both work for my use case.

2 Answers2

0

I used the suggestion above and It fixed my issue.

myip=$(echo $SSH_CONNECTION | awk '{print $1}')

This second approach also seems to work:

myip=$(echo $SSH_CLIENT | awk '{print $1}')

Thanks everyone!

0

If you look at the source code of the GNU implementation of who, you see:

  if (hard_locale (LC_TIME))
    {
      time_format = "%Y-%m-%d %H:%M";
      time_format_width = 4 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2;
    }
  else
    {
      time_format = "%b %e %H:%M";
      time_format_width = 3 + 1 + 2 + 1 + 2 + 1 + 2;
    }

The declaration of hard_locale() in gnulib describes it as:

 /* Return true if the specified CATEGORY of the current locale is hard, i.e.
   different from the C or POSIX locale that has a fixed behavior.
   CATEGORY must be one of the LC_* values, but not LC_ALL.  */
 extern bool hard_locale (int category);

So,

  • in the C/POSIX locale, you get <EnglishMonthNameAbbreviation> <SpacePaddedDayOfTheMonth> <ZeroPaddedHour>:<ZeroPaddedMinute>
  • in other locales: a standard ISO8601-style YYYY-MM-DD HH:MM date.

The locale for the LC_TIME category is determined by the LC_ALL env variable, or LC_TIME variable if LC_ALL is not set or LANG if neither are set. If that's C, POSIX or any string for which the system has no installed locale or if all 3 variables are unset, you get the C/POSIX locale.

The ssh command can pass the LANG and LC_* variables across to the server and it does by default on many Unix-like systems. sshd on many Unix-like systems are also configured to accept those LANG and LC_* variables by default. Microsoft Windows is not a Unix-like system though. Even if the ssh client you use there passes those variables across, it's unlikely that there be some LANG and LC_* variables in the environment containing a locale name that the server supports.

That would explain why you get the C-like date format when sshing from Windows and the ISO8601-style one when sshing from another Unix-like machine.

To get a consistent format, you can force the locale to C by running who with:

LC_ALL=C who -m

But here, it seems you rather want to extract the part between the first occurrence of ( in the line and the last occurrence of ), containing information of where the tty was logged in from, which you could do with:

who -m | perl -ne 'print $1 if /\((.*)\)/'

For ttys created by sshd and provided those environment variables were not cleared (like for instance by sudo or su -), you can extract the IP address of the ssh client from the SSH_CLIENT variable, with:

ipaddress="${SSH_CLIENT%% *}"