在 pts 登录的“last”输出中缺少 IP 信息的原因?

Thi*_*his 18 linux login bash terminal centos

我有五个 CentOS 6 linux 系统在工作,并且遇到了一个相当奇怪的问题,似乎只发生在我拥有的所有 linux 系统中的用户 ID ......这是我从last命令中排除的条目的问题示例.. .

mpenning pts/19                        Fri Nov 16 10:32 - 10:35  (00:03)
mpenning pts/17                        Fri Nov 16 10:21 - 10:42  (00:21)
bill     pts/15       sol-bill.local   Fri Nov 16 10:19 - 10:36  (00:16)
mpenning pts/1        192.0.2.91       Fri Nov 16 10:17 - 10:49 (12+00:31)
kkim14   pts/14       192.0.2.225      Thu Nov 15 18:02 - 15:17 (4+21:15)
gduarte  pts/10       192.0.2.135      Thu Nov 15 12:33 - 08:10 (11+19:36)
gduarte  pts/9        192.0.2.135      Thu Nov 15 12:31 - 08:10 (11+19:38)
kkim14   pts/0        :0.0             Thu Nov 15 12:27 - 15:17 (5+02:49)
gduarte  pts/6        192.0.2.135      Thu Nov 15 11:44 - 08:10 (11+20:25)
kkim14   pts/13       192.0.2.225      Thu Nov 15 09:56 - 15:17 (5+05:20)
kkim14   pts/12       192.0.2.225      Thu Nov 15 08:28 - 15:17 (5+06:49)
kkim14   pts/11       192.0.2.225      Thu Nov 15 08:26 - 15:17 (5+06:50)
dspencer pts/8        192.0.2.130      Wed Nov 14 18:24   still logged in
mpenning pts/18       alpha-console-1. Mon Nov 12 14:41 - 14:46  (00:04)
Run Code Online (Sandbox Code Playgroud)

您可以在上面看到我的两个 pts 登录条目,它们没有关联的源 IP 地址。我的 CentOS 机器有多达六个其他用户共享系统。大约 10% 的我的登录看到这个问题,但没有其他用户名表现出这种行为。没有/var/log/secure源 IP 地址的条目没有条目。

问题

考虑到我在这些系统上保留的脚本类型(它们控制着我们的大部分网络基础设施),我对此感到有些害怕,并想了解是什么导致我的登录偶尔会错过源地址。

  • 为什么last -i显示0.0.0.0点线项目(另见这个答案
  • 有什么东西(恶意活动除外)可以合理地解释这种行为?
  • 除了 bash 历史时间戳之外,我还能做其他事情来追踪问题吗?

信息性

自从这开始发生以来,我启用了bash历史时间戳(即HISTTIMEFORMAT="%y-%m-%d %T "in .bash_profile)并添加了一些其他 bash 历史黑客;然而,这并没有提供关于先前事件中发生了什么的线索。

所有系统都运行 CentOS 6.3 ...

[mpenning@typo ~]$ uname -a
Linux typo.local 2.6.32-279.9.1.el6.x86_64 #1 SMP Tue Sep 25 21:43:11 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
[mpenning@typo ~]$
Run Code Online (Sandbox Code Playgroud)

编辑

如果我使用last -i mpenning,我会看到这样的条目......

mpenning pts/19       0.0.0.0          Fri Nov 16 10:32 - 10:35  (00:03)
mpenning pts/17       0.0.0.0          Fri Nov 16 10:21 - 10:42  (00:21)
Run Code Online (Sandbox Code Playgroud)

试图回答的人请注意:我没有使用screen命令或 GUI登录。我所有的登录都来自 SSH;要获得赏金奖,您必须引用权威参考资料来解释last -i 0.0.0.0仅通过 SSH 获取的条目。

编辑 2(对于 ewwhite 的问题)

/etc/resolv.conf(请注意,我.locallast上面的输出中使用了addrs来隐藏我公司的信息)

[mpenning@sasmars network]$ cat /etc/resolv.conf
nameserver 192.0.2.40
nameserver 192.0.2.60
domain mycompany.com
search mycompany.com
[mpenning@sasmars network]$
Run Code Online (Sandbox Code Playgroud)

/etc/hosts info(请注意,此自定义主机文件仅存在于存在这些问题的其中一台机器上)

[mpenning@sasmars network]$ cat /etc/hosts
127.0.0.1       localhost.localdomain localhost
192.0.2.44      sasmars.mycompany.com sasmars
::1             localhost6.localdomain6 localhost6

## Temporary kludge until I add reverse hostname mappings...
## Firewalls
192.0.2.254     a2-inet-fw1
192.0.2.253     a2-inet-fw2
192.0.2.254     a2-wan-fw1
192.0.2.253     a2-wan-fw2
192.0.2.201     a2-fab-fw1
192.0.2.202     a2-fab-fw2
192.0.2.203     t1-eds-fw1
192.0.2.42      sasvpn
192.0.2.246     sasasa1
192.0.2.10      sasoutfw1
## Wireless
192.0.2.6       saswcs1
192.0.2.2       l2wlc3
192.0.2.4       l2wlc4
192.0.2.12      f2wlc5
192.0.2.16      f2wlc6
192.0.2.14      f2wlc1
192.0.2.8       f2wlc2
[mpenning@sasmars network]$
Run Code Online (Sandbox Code Playgroud)

sftp/var/log/secure*输出

Dec 26 10:36:37 sasmars sshd[26016]: pam_sm_authenticate: called (pam_tacplus v1.3.7)
Dec 26 10:36:37 sasmars sshd[26016]: pam_sm_authenticate: user [mpenning] obtained
Dec 26 10:36:37 sasmars sshd[26016]: tacacs_get_password: called
Dec 26 10:36:37 sasmars sshd[26016]: tacacs_get_password: obtained password
Dec 26 10:36:37 sasmars sshd[26016]: pam_sm_authenticate: password obtained
Dec 26 10:36:37 sasmars sshd[26016]: pam_sm_authenticate: tty [ssh] obtained
Dec 26 10:36:37 sasmars sshd[26016]: pam_sm_authenticate: rhost [192.0.2.91] obtained
Dec 26 10:36:37 sasmars sshd[26016]: pam_sm_authenticate: trying srv 0
Dec 26 10:36:38 sasmars sshd[26016]: Accepted password for mpenning from 192.0.2.91 port 55118 ssh2
Dec 26 10:36:38 sasmars sshd[26016]: pam_sm_setcred: called (pam_tacplus v1.3.7)
Dec 26 10:36:38 sasmars sshd[26016]: pam_unix(sshd:session): session opened for user mpenning by (uid=0)
Dec 26 10:36:38 sasmars sshd[26018]: pam_sm_setcred: called (pam_tacplus v1.3.7)
Dec 26 10:36:38 sasmars sshd[26018]: subsystem request for sftp
Dec 26 10:37:20 sasmars sshd[26016]: pam_unix(sshd:session): session closed for user mpenning
Dec 26 10:37:20 sasmars sshd[26016]: pam_sm_setcred: called (pam_tacplus v1.3.7)
Run Code Online (Sandbox Code Playgroud)

最终决议

我下面的回答

Soh*_*rty 12

这对我来说绝对令人费解。它应该使用一些 DNS 名称或 IP 地址。我也检查了last.c文件,但我仍然找不到为什么它没有显示任何内容。可能给了一些时间,我可以弄清楚大约 0.0.0.0 的部分。

int dns_lookup(char *result, int size, int useip, int32_t *a)
307 {
308     struct sockaddr_in  sin;
309     struct sockaddr_in6 sin6;
310     struct sockaddr     *sa;
311     int         salen, flags;
312     int         mapped = 0;
313 
314     flags = useip ? NI_NUMERICHOST : 0;
315 
316     /*
317      *  IPv4 or IPv6 ?
318      *  1. If last 3 4bytes are 0, must be IPv4
319      *  2. If IPv6 in IPv4, handle as IPv4
320      *  3. Anything else is IPv6
321      *
322      *  Ugly.
323      */
324     if (a[0] == 0 && a[1] == 0 && a[2] == htonl (0xffff))
325         mapped = 1;
326 
327     if (mapped || (a[1] == 0 && a[2] == 0 && a[3] == 0)) {
328         /* IPv4 */
329         sin.sin_family = AF_INET;
330         sin.sin_port = 0;
331         sin.sin_addr.s_addr = mapped ? a[3] : a[0];
332         sa = (struct sockaddr *)&sin;
333         salen = sizeof(sin);
334     } else {
335         /* IPv6 */
336         memset(&sin6, 0, sizeof(sin6));
337         sin6.sin6_family = AF_INET6;
338         sin6.sin6_port = 0;
339         memcpy(sin6.sin6_addr.s6_addr, a, 16);
340         sa = (struct sockaddr *)&sin6;
341         salen = sizeof(sin6);
342     }
343 
344     return getnameinfo(sa, salen, result, size, NULL, 0, flags);
345 }
Run Code Online (Sandbox Code Playgroud)

上下文中使用的两个全局变量就是这些。

int usedns = 0;     /* Use DNS to lookup the hostname. */
72 int useip = 0;       /* Print IP address in number format */
Run Code Online (Sandbox Code Playgroud)

因此,理论上,它应该使用 dns 或 IP。

我会看看我是否可以进一步挖掘。但 ewwhite 提出的问题是有效的。


Joh*_*Siu 8

(1) 基于OPlast输出

通过 ssh 登录后,可以 ssh 到 localhost 并获取 0.0.0.0 以last -i供稍后使用。

基于 OP 日志的前四行

mpenning pts/19                        Fri Nov 16 10:32 - 10:35  (00:03)
mpenning pts/17                        Fri Nov 16 10:21 - 10:42  (00:21)
bill     pts/15       sol-bill.local   Fri Nov 16 10:19 - 10:36  (00:16)
mpenning pts/1        192.0.2.91       Fri Nov 16 10:17 - 10:49 (12+00:31)
Run Code Online (Sandbox Code Playgroud)

pts/19登录是在pts/17登录期间内。

pts/17登录是在pts/1 登录期间内。

对于这个特定的事件,从 192.0.2.91( pty/1)猜测 OP ssh 是合乎逻辑的,然后在该 ssh 会话中,在本地 ( ssh localhost) 再次登录到服务器 ( pts/17),然后再次 ( pts/19)。

请检查这种重叠是否与其他事件发生。

以下可能有助于查明原因

  • 你使用 ssh 密钥吗?如果是这样,在服务器上,您是否设置了 ssh-key 本地登录?
  • 检查或发布相同时间范围的 /var/log/secure。它可能会提供一些提示。
  • 检查您使用的脚本
  • 检查您使用的 shell 别名
  • 检查您的命令历史记录

(2) 额外的Secnario

场景 1 - sudo 和终端

  1. UserA 登录 X 窗口
  2. 打开一个终端窗口,做 xhost + localhost
  3. su - UserB或者sudo su - UserB打开一个新的终端(xterm、gnome-terminal 等)
  4. UserB 将显示为 0.0.0.0 last -i

su - UserBUserB最后不会注册为登录名,但打开终端会。

场景 2 - 登录

  1. ssh 进入服务器
  2. 类型 sudo login
  3. 以您自己的身份登录
  4. 检查lastlast -i

last不显示login session. last -i将 IP 0.0.0.0 用于login session.

john@U64D211:~$ last -5
john     pts/0                         Sun Dec 23 20:50   still logged in   
john     pts/0                         Sun Dec 23 20:50 - 20:50  (00:00)    
john     pts/0        :0               Sun Dec 23 20:50 - 20:50  (00:00)    
reboot   system boot  3.2.0-35-generic Sun Dec 23 20:49 - 20:50  (00:01)    
john     pts/2        js.example.com   Sun Dec 23 17:14 - crash  (03:34)    

wtmp begins Sat Dec  1 06:30:46 2012
john@U64D211:~$ last -5i
john     pts/0        0.0.0.0          Sun Dec 23 20:50   still logged in   
john     pts/0        0.0.0.0          Sun Dec 23 20:50 - 20:50  (00:00)    
john     pts/0        0.0.0.0          Sun Dec 23 20:50 - 20:50  (00:00)    
reboot   system boot  0.0.0.0          Sun Dec 23 20:49 - 20:50  (00:01)    
john     pts/2        192.168.1.90     Sun Dec 23 17:14 - crash  (03:34)    

wtmp begins Sat Dec  1 06:30:46 2012
Run Code Online (Sandbox Code Playgroud)

Mife的回答已经显示了last.c. last显示空主机名/IP的原因是因为ut_host这些记录实际上是空的。要获得完整的 wtmp 结构,请man wtmp在任何 linux 系统上执行。

这里的 2 个场景表明,即使是标准包,在某些情况下,也会创建它们。

(3) Bash 历史黑客

它仅在会话bash用作交互式 shell时才有效。

.bashrc并且.bash_profile只被 使用bash

如果会话使用任何其他 shell(sh、csh 等)或直接执行程序,它们将不会自动获取,也不会有 bash 历史记录。

(4) 流程核算

由于 OP 没有提及secure文件,我将假设这是一个死胡同,它实际上提供了现在的提示。

如果以下假设正确

`last` 0.0.0.0 entries are actually created with in OP own session
Run Code Online (Sandbox Code Playgroud)

auth.log(debian)/secure(CentOS) 不会有帮助。因为其中只记录了与身份验证相关的操作。

wtmp/utmp,由于其数据结构的限制,也是一个死胡同。没有关于是什么创建它们的信息。

这给我们留下了一个选择,流程会计。这是一把大枪,必须谨慎使用。

  1. 可能违反公司政策
  2. 共享系统上的其他用户可能对启用它不满意/不舒服
  3. 日志文件可能会使用大量磁盘空间。密切关注文件大小增长率。

根据这篇文章,psacct 包版本应该是6.3.2-56或更高版本。

如果要使用它,并且/var/log空间有限,请将 acct 日志文件更改为 下的目录(仅限 root 访问)/home,该目录通常有更多空间。

这真的是大炮。OP发生率为10%,一周内应该会有结果。如果在此期间,lastacct log 中出现空条目,但没有任何内容,这将成为一个神秘的 情况,需要采取一些激烈的行动

以下是示例输出 lastcomm

lesspipe               john     pts/8      0.02 secs Mon Dec 24 17:10
lesspipe          F    john     pts/8      0.00 secs Mon Dec 24 17:10
dirname                john     pts/8      0.00 secs Mon Dec 24 17:10
basename               john     pts/8      0.00 secs Mon Dec 24 17:10
kworker/1:2       F    root     __         0.00 secs Mon Dec 24 16:54
tty                    john     pts/6      0.01 secs Mon Dec 24 17:09
tty                    john     pts/4      0.01 secs Mon Dec 24 17:09
cron              F    root     __         0.05 secs Mon Dec 24 17:09
sh               S     root     __         0.01 secs Mon Dec 24 17:09
find                   root     __         0.01 secs Mon Dec 24 17:09
maxlifetime            root     __         0.00 secs Mon Dec 24 17:09
php5                   root     __         0.23 secs Mon Dec 24 17:09
which                  root     __         0.00 secs Mon Dec 24 17:09
lastcomm               root     pts/0      0.01 secs Mon Dec 24 17:08
tty                    john     pts/1      0.01 secs Mon Dec 24 17:08
dconf worker         X john     __         5.46 secs Mon Dec 24 16:58
lastcomm               root     pts/7      0.04 secs Mon Dec 24 17:05
mesg             S     root     pts/7      0.00 secs Mon Dec 24 17:05
bash              F    root     pts/7      0.00 secs Mon Dec 24 17:05
dircolors              root     pts/7      0.00 secs Mon Dec 24 17:05
Run Code Online (Sandbox Code Playgroud)

您还可以使用“dump-acct”来显示更多信息。

PS1:我尝试打开几个终端和 ssh 会话。目前尚不清楚(或不容易确定)是什么打开了一个新的 pts。但是,它确实显示了在该 pts/会话中运行的所有内容。

PS2:Mike 的一篇关于使用 acct 的博客文章。


Mat*_*Ife 8

所以我最后在调试器中运行,希望至少可以为您的问题提供一些答案。我的感觉是根本原因虽然更深。

为什么 last -i 显示 0.0.0.0 为 pts 行条目

解释这一点的最好方法是当你通过 -i时会发生什么。

原因是在这个代码部分 last.c

if (usedns || useip)
  r = dns_lookup(domain, sizeof(domain), useip, p->ut_addr_v6);
if (r < 0) {
   len = UT_HOSTSIZE;
   if (len >= sizeof(domain)) len = sizeof(domain) - 1;
   domain[0] = 0;
   strncat(domain, p->ut_host, len);
}
Run Code Online (Sandbox Code Playgroud)

这两个usednsuseip(使用默认选项)不会被标记。这使得逻辑该结构的复制出p->ut_host根据该man utmp包含所记录的任何写入远程登录名utmp

char ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or
                              kernel version for run-level
                              messages */
Run Code Online (Sandbox Code Playgroud)

在您的情况下,此处的值为零。这就是为什么当您运行时last什么都没有出现的原因。

last -ithen dns_lookup 被调用的情况下。这将传递要通过 DNS 解析的条目 (p->ut_addr_v6)。在您的情况下,此值包含零。

大多数dns_lookup是橱窗装饰和欺骗。基本上重要的是功能getnameinfo。这是一个库调用,在这种情况下,它将尽力解析存储在ut_addr_v6. 当此条目包含零(例如在您的情况下)时,您实际上是在将其解析0.0.0.0last -i输出时发生的情况。

有什么东西(恶意活动除外)可以合理地解释这种行为?

好吧,它可能是一个错误或疏忽。它不太可能是恶意的,因为作为攻击者留下任何痕迹而不是省略源地址似乎很愚蠢。

到目前为止,答案的重点一直是看错了地方。last只是阅读utmpwtmp。然而last,它正在尽最大努力利用它拥有的数据。

您的根本原因在于utmp写入的方式

虽然一些应用程序直接写入utmp我猜你的问题的根源在于sshd处理会话管理的方式。

除了 bash 历史时间戳之外,我还能做其他事情来追踪问题吗?

utmp通常不可写,也不应该是。utmp由旨在让您登录并设置会话的应用程序编写。在你的情况下是sshd

为什么 sshd 没有正确处理您的用户是非常奇怪的,因为它应该正确复制您来自的主机名。这是调试工作可能应该关注的地方。首先将 sshd 的调试输出添加到您的日志中,看看是否出现任何异常情况。

如果您想解决该问题(或者,甚至可能发现有关该问题的更多信息),您可以通过将其添加到 /etc/pam.d/sshd的会话条目来pam_lastlog进行管理。utmp

事实上,检查它是否已经存在不会有什么坏处——因为pam_lastlog包含一个nohost选项,它肯定会解释你正在经历的行为。

最后,您根本无法使用 last。aulast通过审计子系统做同样的工作。

可能值得一试,看看它是否至少能写出正确的地址。如果没有,那么您的问题一定出在 sshd 上,因为 sshd 会在不同的子系统(如 utmp 或审计)中传递 DNS 名称。


Nap*_*r_X 5

当您登录到一台机器时,这些可能是最后一个命令中的几个条目。

geekride   tty2                        Fri Dec 21 15:45 - 15:45  (00:00)    
geekride   pts/1                       Fri Dec 21 13:45   still logged in   
geekride   pts/1        :pts/0:S.0     Thu Dec  6 12:49 - 00:40  (11:50)    
geekride   pts/1        10.31.33.47    Thu Dec  6 12:49 - 00:40  (11:50)    
Run Code Online (Sandbox Code Playgroud)

当您通过终端或控制台按 CTRL+ALT+F1-6 登录时,会出现带有 tty* 的第一个条目。从它正在使用的终端来看,它非常清楚。

当您登录机器​​并在 GUI 中打开终端窗口时,通常会出现第二个条目。即使您在同一终端窗口中打开一个新选项卡,也会有一个条目。

当您通过 SSH 登录后打开屏幕会话时,会出现第三种类型的条目。这也会在那里创建一个没有任何 IP 地址的条目。

第四个条目很正常,每个人都理解。

如果您last -i使用以下条目,您将看到如下内容:

geekride   tty2         0.0.0.0        Fri Dec 21 15:45 - 15:45  (00:00)    
geekride   pts/9        0.0.0.0        Fri Dec 21 13:45   still logged in   
geekride   pts/1        0.0.0.0        Thu Dec  6 12:49 - 00:40  (11:50)    
Run Code Online (Sandbox Code Playgroud)

我非常确定您的情况属于两种情况中的任何一种,一种是 GUI 中的终端窗口,另一种是屏幕会话。

希望这有帮助。

  • 我没有对任何“0.0.0.0”条目使用 GUI 或“屏幕”。我只在安装机器时使用 GUI(大约八月/九月)。在那之后,我看到许多“0.0.0.0”pts 条目。 (2认同)

Joh*_*Siu 4

scriptRedHat 和 Debian 之间的行为差​​异

链接库

CentOS 6.3 - 脚本(util-linux-ng 2.17.2)

#ldd /usr/bin/script

linux-vdso.so.1 =>  (0x00007fff077ff000)
libutil.so.1 => /lib64/libutil.so.1 (0x00007f309f5d1000)
libutempter.so.0 => /usr/lib64/libutempter.so.0 (0x00007f309f3cf000)
libc.so.6 => /lib64/libc.so.6 (0x00007f309f03b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f309f7e1000)
Run Code Online (Sandbox Code Playgroud)

Ubuntu 12.04 - 脚本(util-linux 2.20.1)

#ldd /usr/bin/script

linux-vdso.so.1 =>  (0x00007fff375ff000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fc0d7ab0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc0d76f1000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc0d7cdc000)
Run Code Online (Sandbox Code Playgroud)

PTY

基于上游源代码script两个版本都打开新的pty。以下是测试。

乌班图12.04

john@U64D211:~/tmp$ ls /dev/pts
0  1  5  8  ptmx
john@U64D211:~/tmp$ script
Script started, file is typescript
john@U64D211:~/tmp$ ls /dev/pts
0  1  2  5  8  ptmx
john@U64D211:~/tmp$ last -i
john     pts/0        0.0.0.0          Sat Jan  5 09:09   still logged in   
reboot   system boot  0.0.0.0          Sat Jan  5 09:08 - 09:52  (00:44)    
john     pts/0        0.0.0.0          Thu Jan  3 00:50 - 01:42  (00:52)    
reboot   system boot  0.0.0.0          Thu Jan  3 00:48 - 01:43  (00:54)    

wtmp begins Tue Jan  1 20:48:28 2013
john@U64D211:~/tmp$ exit
exit
Script done, file is typescript
john@U64D211:~/tmp$ ls /dev/pts
0  1  5  8  ptmx
john@U64D211:~/tmp$ 
Run Code Online (Sandbox Code Playgroud)

Ubuntu 12.04script确实开辟了一个新的pts(2)。它只是没有更新/var/log/wtmp

操作系统6

我将跳过测试,因为我们已经知道script打开 pty 并注册 wtmp。

利布坦佩尔

  • 项目: http: //freecode.com/projects/libutempter
  • 说明:libutempter 为 screen 和 xterm 等终端仿真器提供了一个库接口,用于将用户会话记录到 utmp 和 wtmp 文件中。

所以主要的区别似乎是libutempter.so.0CentOSscript链接的额外库()。

使用 Ubuntu 12.04 进行测试

script使用 libutempter编译

john@U64D211:~/tmp/util-linux-2.20.1$ sudo apt-get install libutempter-dev
john@U64D211:~/tmp/util-linux-2.20.1$ ./configure --with-utempter
john@U64D211:~/tmp/util-linux-2.20.1$ make
john@U64D211:~/tmp/util-linux-2.20.1$ cd term-utils/
john@U64D211:~/tmp/util-linux-2.20.1/term-utils$ ldd ./script
linux-vdso.so.1 =>  (0x00007fff54dff000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f289e635000)
libutempter.so.0 => /usr/lib/libutempter.so.0 (0x00007f289e432000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f289e072000)
/lib64/ld-linux-x86-64.so.2 (0x00007f289e861000)
Run Code Online (Sandbox Code Playgroud)

测试

跑步前script

john@U64D211:~/tmp/util-linux-2.20.1/term-utils$ ls /dev/pts
0  1  5  8  ptmx
john@U64D211:~/tmp/util-linux-2.20.1/term-utils$ last -i
john     pts/0        0.0.0.0          Sat Jan  5 09:09   still logged in   
reboot   system boot  0.0.0.0          Sat Jan  5 09:08 - 10:37  (01:28)    
john     pts/0        0.0.0.0          Thu Jan  3 00:50 - 01:42  (00:52)    
reboot   system boot  0.0.0.0          Thu Jan  3 00:48 - 01:43  (00:54)    

wtmp begins Tue Jan  1 20:48:28 2013
Run Code Online (Sandbox Code Playgroud)

之内script

john@U64D211:~/tmp/util-linux-2.20.1/term-utils$ ./script
Script started, file is typescript
john@U64D211:~/tmp/util-linux-2.20.1/term-utils$ ls /dev/pts
0  1  2  5  8  ptmx
john@U64D211:~/tmp/util-linux-2.20.1/term-utils$ last -i
john     pts/2        0.0.0.0          Sat Jan  5 10:37   still logged in   
john     pts/0        0.0.0.0          Sat Jan  5 09:09   still logged in   
reboot   system boot  0.0.0.0          Sat Jan  5 09:08 - 10:37  (01:29)    
john     pts/0        0.0.0.0          Thu Jan  3 00:50 - 01:42  (00:52)    
reboot   system boot  0.0.0.0          Thu Jan  3 00:48 - 01:43  (00:54)    

wtmp begins Tue Jan  1 20:48:28 2013
john@U64D211:~/tmp/util-linux-2.20.1/term-utils$ exit
exit
Script done, file is typescript
Run Code Online (Sandbox Code Playgroud)

script结束后

john@U64D211:~/tmp/util-linux-2.20.1/term-utils$ ls /dev/pts
0  1  5  8  ptmx
john@U64D211:~/tmp/util-linux-2.20.1/term-utils$ last -i
john     pts/2        0.0.0.0          Sat Jan  5 10:37 - 10:37  (00:00)    
john     pts/0        0.0.0.0          Sat Jan  5 09:09   still logged in   
reboot   system boot  0.0.0.0          Sat Jan  5 09:08 - 10:37  (01:29)    
john     pts/0        0.0.0.0          Thu Jan  3 00:50 - 01:42  (00:52)    
reboot   system boot  0.0.0.0          Thu Jan  3 00:48 - 01:43  (00:54)    

wtmp begins Tue Jan  1 20:48:28 2013
john@U64D211:~/tmp/util-linux-2.20.1/term-utils$ last
john     pts/2                         Sat Jan  5 10:37 - 10:37  (00:00)    
john     pts/0        :0               Sat Jan  5 09:09   still logged in   
reboot   system boot  3.2.0-35-generic Sat Jan  5 09:08 - 10:38  (01:30)    
john     pts/0        :0               Thu Jan  3 00:50 - 01:42  (00:52)    
reboot   system boot  3.2.0-35-generic Thu Jan  3 00:48 - 01:43  (00:54)    

wtmp begins Tue Jan  1 20:48:28 2013
Run Code Online (Sandbox Code Playgroud)

主机名为空的根本原因

是的,script.cwtmp使用空主机名创建条目。查看util-linux-2.20.1/term-utils/script.c第 245-247 行中的以下代码块

#ifdef HAVE_LIBUTEMPTER
    utempter_add_record(master, NULL);
#endif
Run Code Online (Sandbox Code Playgroud)

依据libutempter-1.1.5/utempter.h

extern int utempter_add_record (int master_fd, const char *hostname);
Run Code Online (Sandbox Code Playgroud)

实际上script.c是将空主机名传递到utempter_add_record.

红帽向后移植

有趣的是,upstreamutil-linux-ng-2.17.2实际上并不支持libutempter. 看来 Redhat 决定重新添加该支持。

john@U64D211:~/tmp/util-linux-ng-2.17.2$ ./configure --help|grep utemp
Run Code Online (Sandbox Code Playgroud)

上述命令返回空结果。

结论

因此,两个发行版之间的行为差​​异不是错误,而是一种选择。RedHat 决定支持该功能,而 Debian 则跳过了它。