如果我通过 SSH 从另一台 Linux 服务器连接到我的 Debian 12 服务器并运行谁命令,它显示以下内容:
test-user pts/1 2024-01-24 11:13 (xx.xx.xx.xx)
但是,如果我从 Windows 11 计算机通过 Windows 终端或使用第三方应用程序连接到使用相同的确切用户并运行相同的 Debian 12 服务器谁命令,日期/时间格式显示不同。
test-user pts/0 Jan 24 11:15 (xx.xx.xx.xx)
我正在运行这条线/etc/配置文件确定每次登录时用户的 IP 地址,但它无法正常工作,因为输出不同并且这些空格正在改变结果。
myip=$(who -m | awk '{print substr($5, 2, length($5) - 2)}')
有没有办法控制日期/时间输出WHO命令?什么可能导致这种行为?
更新
从以下位置运行区域设置命令:
从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=
从 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=
请注意,我连接的所有 Linux 服务器似乎都没有发生这种情况。它有所不同,并在下面的解决方案中进行了解释。
当我根据下面的解释了解根本原因时,我选择使用这些建议,它们都适用于我的用例。
答案1
如果你看GNU 实现的源代码who
, 你看:
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; }
这hard_locale()
gnulib 中的声明将其描述为:
/* 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);
所以,
- 在 C/POSIX 语言环境中,您会得到
<EnglishMonthNameAbbreviation> <SpacePaddedDayOfTheMonth> <ZeroPaddedHour>:<ZeroPaddedMinute>
- 在其他语言环境中:标准 ISO8601 样式的 YYYY-MM-DD HH:MM 日期。
LC_TIME 类别的区域设置由 env 变量确定LC_ALL
,如果未设置或两者均未设置,则由该LC_TIME
变量确定。如果是,或者系统没有安装语言环境的任何字符串,或者如果所有 3 个变量都未设置,则您将获得 C/POSIX 语言环境。LC_ALL
LANG
C
POSIX
该ssh
命令可以将LANG
和LC_*
变量传递到服务器,并且在许多类 Unix 系统上默认这样做。sshd
在许多类 Unix 系统上也配置为接受默认情况下这些LANG
和LC_*
变量。但 Microsoft Windows 并不是类 Unix 系统。即使ssh
您在那里使用的客户端传递这些变量,环境中也不太可能存在包含服务器支持的区域设置名称的某些变量LANG
。LC_*
这就解释了为什么C
当从 Windows 进行 ing 时会得到 -like 日期格式ssh
,而当从另一台类 Unix 机器进行 sshing 时会得到 ISO8601 样式的日期格式。
要获得一致的格式,您可以C
通过运行以下命令强制区域设置who
:
LC_ALL=C who -m
(
但在这里,您似乎更想提取行中第一次出现的 和 最后一次出现的 之间的部分)
,其中包含 tty 登录位置的信息,您可以这样做:
who -m | perl -ne 'print $1 if /\((.*)\)/'
对于由 tty 创建的sshd
并且假设这些环境变量未被清除(例如由sudo
或su -
),您可以从变量中提取 ssh 客户端的 IP 地址SSH_CLIENT
,方法是:
ipaddress="${SSH_CLIENT%% *}"
答案2
我使用了上面的建议,它解决了我的问题。
myip=$(echo $SSH_CONNECTION | awk '{print $1}')
第二种方法似乎也有效:
myip=$(echo $SSH_CLIENT | awk '{print $1}')
感谢大家!