在最近的公司计算机上启动时崩溃

Gil*_*il' 63 linux startup systemd crash intel

经过最近的一些更新,我的电脑不再启动!这是我可以确定的:

  • 这是一台最近由公司 IT 提供给我的计算机。它有一个最新的 Intel CPU(Skylake 一代)。
  • 计算机运行 Ubuntu 16.04。
  • 计算机上次正确启动是在 3 月的某个时间。问题可能是由于软件更新或硬件错误。
  • 我有另一台运行 16.04 的计算机,安装了几乎相同的软件(我用过apt-clone),它工作得很好。它有不同的硬件(也是 amd64,但不同的 CPU、不同的 GPU 等)。
  • 内核确实启动了,initrd 工作正常。当我以图形模式启动启动画面时,系统提示我输入 dm-crypt 卷的密码,我看到的最后一件事是它已成功安装。
  • 挂起发生在我收到登录提示之前。当计算机挂起时,这是一个硬挂。即使Alt+SysRq没有响应。由于风扇全速开启,因此 CPU 显然固定在 100%。
  • 我仍然拥有重新启动前正在运行的内核。当我在 Grub 菜单中选择这个内核时,我得到了同样的锁定。所以看起来这是一个预先存在的内核错误,它被其他东西触发了——但是什么?
  • 如果我关闭启动画面(splashlinuxGrub的命令行中删除),我会看到许多服务正在启动,然后它会锁定。
  • 我可以通过添加init=/bin/shlinuxGrub的命令行来获得 root shell 。我什至可以通过添加进一步

    systemd.unit=basic.target systemd.shell
    
    Run Code Online (Sandbox Code Playgroud)

    这将启动许多服务并在 tty9 上运行一个 root shell。

  • 如果我systemctl start multi-user.target从那个 root shell运行,计算机就会锁定。所以大概问题是由这些服务之一触发的。
  • 我跑去systemctl list-dependencies multi-user.target看看有哪些服务开始了。我手动一一启动了列出的依赖项,一切都开始了。

因此,这看起来像是由某些软件触发的硬件错误(因为它发生在一台计算机上而不是另一台计算机上)。但是什么软件?由于电脑死机很厉害,我无法获得任何日志。我什至无法获得任何有用的控制台输出。


有用的调试技术:

  • Alt+ SysRq:神奇的 SysRq 键,可让您执行紧急重启等操作。它在非常低的级别访问内核,因此除了最严重的崩溃之外,它可以在所有情况下工作。在我的情况下,Alt+SysRq没有响应,这显示了崩溃的深度。
  • 要修改开机参数,开机Shift后按住几秒。您需要在 BIOS 初始化键盘之后,但在操作系统启动之前按下它。这使得Grub菜单出现。
  • 在 Grub 菜单中,按e可编辑菜单项的命令行。要更改 Linux 引导参数,请导航到以linux. 在现代 Ubuntu 上,您会在“Ubuntu 的高级选项”下找到旧内核。对命令行进行所需的更改后,按Ctrl+x启动。您在此处所做的任何更改仅针对此引导,它们不会保存到磁盘。
  • linux命令行上的一些有用选项:
    • quiet nosplash隐藏几乎所有的启动消息。删除它们以在引导期间在控制台上获取消息,这对于诊断问题是必要的。
    • recovery给你一个几乎没有服务的 root shell。您需要知道 root 密码。“恢复模式”菜单条目使用此。
    • init=/bin/sh为您提供一个根本没有服务的 root shell。要恢复正常启动,请运行exec init. 此时您可以传递 systemd 选项,例如exec init --unit=basic.target启动 init 和一些服务(请注意,这不会以任何方式启动登录,因此您最好在另一个控制台上运行一个 shell)。请注意,根文件系统以只读方式挂载;运行mount -o remount,rw /以能够写入它。
    • systemd.unit=basic.target启动一组非常基本的服务。请注意,这不包括任何登录方式!您可以通过systemctl set-default basic.target在 root 提示符下运行来将其设为默认值。要恢复原始默认目标,请运行systemctl set-default graphical.target(或systemctl set-default multi-user.target对于没有 GUI 的服务器)。
    • systemd.debug-shell在 tty9 上启动一个 root shell。您可以通过systemctl enable debug-shell在 root 提示符下运行来为每次引导启用此功能。解决了问题后,不要忘记禁用它systemctl disable debug-shell。按Alt+F9切换到 tty9。
    • 另请参阅Fedora systemd 提示Arch Linux 引导问题提示

Gil*_*il' 71

问题

事实证明,我的问题是(某些?)Skylake CPU 上最新的 Intel 微码与最近的 Linux 内核之间的一个已知问题,主要由sssd触发。请参阅Ubuntu 错误 #1759920“intel-microcode 3.20180312.0 导致登录屏幕锁定(带有 linux-image-4.13.0-37-generic)”,以及许多其他与相同问题有关的错误,例如Ubuntu 错误 #1746806“sssd 似乎使 AWS c5 和 m5 实例崩溃,导致 100% CPU”Ubuntu 错误 #1746418“安装 linux-image-4.13.0-32-generic 后启动 Xorg 时系统冻结”。如果出现以下情况,您可能会遇到此错误:

  • 您有一个最新的 Intel CPU。据我所知,这个错误只出现在Skylake CPU 上。
  • 你已经安装了intel-microcode包。恢复到较早的经过测试的内核对我不起作用,因为我只会使用较早的微码运行该内核。
  • 您的计算机已连接到公司网络(通常是 LDAP 或 Active Directory)以进行用户身份验证。尽管还有其他方式可以触发该错误,但运行sssd似乎是最常见的罪魁祸首。也有Xorg 崩溃的报告。

该错误是由于2018 年 1 月发布的Spectre安全问题的缓解措施所致。某些内核代码和某些处理器微代码之间存在不兼容,这会导致在某些情况下锁定。

如何修复

  1. 如果无法正常启动,则需要在 Grub 提示符下编辑内核命令行。有关解释和获取 root shell 的可能方法,请参阅问题。
  2. 此特定错误的解决方法是noibpb参数添加到内核​​命令行( 1746418/141759920/56 )。这应该可以让您正常启动并进行一些修复。
    这将禁用导致问题的漏洞缓解,这意味着您的计算机现在容易受到某些攻击。它们是本地攻击,即攻击者需要在您的机器上运行代码,但这些攻击有可能通过 Web 浏览器中的 JavaScript 等方式进行。
    如果您没有任何其他方法,您可以通过添加noibpb到内核​​命令行来使其永久化,直到您获得一个固定的内核。
  3. 在 Ubuntu 中,预计会在 2018 年 4 月 23 日这一周进行修复,大概是内核 4.4.0-117 和 4.13.0-39。与此同时,Tyler Hicks 已经发布4.44.13 的测试内核

我是如何诊断问题的

我尝试了几件事(请参阅问题)并确定该错误是在到达basic.target和到达之间的某个地方触发的multi-user.target。所以我将默认的 systemd 目标设置为basic.target( systemctl set-default basic.target) 并启用debug-shell服务 ( systemctl enable debug-shell) 以获取 root shell。

systemctl list-dependencies multi-user.target一一运行并手动启动了列出的依赖项。这并没有触发崩溃。

并非所有服务都由systemd直接管理。有些作为Upstart服务进行管理,有些作为SysVinit 脚本进行管理。下面的 shell 脚本运行所有这些。注意:我只测试过一次,它在设计上崩溃了。

#!/bin/sh
wants=$(systemctl show -p Wants multi-user.target | sed 's/^Wants=//' | tr ' ' '\n' | sort)
log=/var/tmp/multi-user-steps-$(date +%Y%m%d-%H%M%S)

log () {
  echo "$* ..." | tee -a "$log"
  sync
  "$@"
  ret=$?
  echo "$* -> $ret" | tee -a "$log"
  sync
  return $ret
}

# systemd services
for service in $wants; do
  log systemctl start $service
  sleep 2
done

# upstart services
for conf in /etc/init/*.conf; do
  service=${conf##*/}; service=${service%.conf}
  log service ${service} start
  sleep 2
done

# sysvinit services
for service in /etc/rc3.d/S*; do
  log ${service} start
  sleep 2
done
Run Code Online (Sandbox Code Playgroud)

我的电脑启动后就死机了sssd。从那里,对“sssd linux kernel hang”的网络搜索使我找到了https://bugs.launchpad.net/cloud-images/+bug/1746806以及诊断和解决方案。

  • @Tonny 微码修复了其他错误,例如 [this](http://gallium.inria.fr/blog/intel-skylake-bug/),以及英特尔未披露的问题。虽然这确实是一个解决方案,但我不放心不应用微代码更新——除了 Spectre/Meltdown 似乎有点匆忙推出。我建议使用 `noipbp` 主要是作为引导到受影响系统的一种方式。我认为这里最好的解决方法是升级内核。 (3认同)