之前我尝试添加该参数nomodeset
来/etc/default/grub
解决与我的笔记本电脑过去启动方式异常有关的另一个问题。但效果不佳。所以我在 grub 菜单中按“e”将其删除。登录后,我改回 grub 文件并更新它。
但是现在当我重新启动时,它会停在一个空白屏幕上,光标闪烁。我重新启动它并在 grub 菜单中按“e”。接下来我更改了
[...]ro quiet splash $vt_handoff
到
[...]ro $vt_handoff quiet splash
然后按 F10 键,加载正常,但图形比使用前要少nomodeset
。问题是每次启动时我都必须这样做。如何使最后的更改永久生效?
附言:我的笔记本电脑在 Ubuntu 18.04 上播放视频时容易崩溃,现在在 19.04 上也容易崩溃(它与 18 和 19 双启动)。在 18 中,我曾经重新启动,之后系统运行良好,但是对于 19,在 grub 菜单上选择 Ubuntu 19 后(崩溃后,播放视频),它就卡住了,我不得不重新安装它。我知道这很可能不是做事的正确方法,欢迎提出建议。
编辑1:正如所提到的如何添加内核启动参数?我知道如何在 grub 文件中添加新参数(如 nomodeset),从而永久更改内核命令,但是它$vt_handoff
已经存在于内核命令中,但不在 grub 文件中,因此我很困惑如何删除它或更改它在参数列表中的顺序?
答案1
源代码
处理生成您想要修改的 GRUB 配置的文件是/etc/grub.d/10_linux
并且内核命令行的 $vt_handoff 元素在其代码中被处理两次(截至我当前安装的版本,v2.04)。
首先(并且与您期望的结果更相关,因为这是处理变量的位置
$vt_handoff
)在第 154-160 行的嵌套 if 块中:... if [ "$vt_handoff" = 1 ]; then for word in $GRUB_CMDLINE_LINUX_DEFAULT; do if [ "$word" = splash ]; then GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT \$vt_handoff" fi done fi ...
然后再次在第 348-358 行的嵌套 if 块中决定为变量设置什么值
$vt_handoff
:... set gfxpayload="${1}" EOF if [ "$vt_handoff" = 1 ]; then cat << 'EOF' if [ "${1}" = "keep" ]; then set vt_handoff=vt.handoff=7 else set vt_handoff= fi EOF fi ...
分析
$GRUB_CMDLINE_LINUX_DEFAULT
在上面显示的第一个实例中,我们看到 Dash shell 解释器将文件中的源值/etc/default/grub
与$vt_handoff
变量名称¹连接起来。 编写的代码选择将后者附加到前者,但您可以将其添加到前面,就像在第 157 行反转重新分配的变量中元素的位置一样容易。$GRUB_CMDLINE_LINUX_DEFAULT
然后它看起来像这样:
...
if [ "$word" = splash ]; then
GRUB_CMDLINE_LINUX_DEFAULT="\$vt_handoff $GRUB_CMDLINE_LINUX_DEFAULT"
fi
...
这无疑是实现您所寻求结果的最直接方法,但它不符合我自己对“永久”解决方案的定义,因为每次您的系统安装 GRUB 更新时,该文件都会被覆盖。鉴于此,我认为这更准确地说是一种“持久”解决方案,因为它确实可以在任何给定 GRUB 软件包版本的生命周期内从一个电源循环到另一个电源循环中存活,但不会再存活下去。
潜在的永久解决方案
使用 GRUB_GFXPAYLOAD_LINUX 的值
由于我们通常建议“与系统一起工作”(如果可能),而不是“与系统对抗”,因此我认为这样做的一个潜在方法存在于/etc/grub.d/10_linux
上述文件中的第二个代码片段中。具体来说,我们看到脚本逻辑评估位置参数,并且只有$vt_handoff
当变量的值为“keep”时才激活该变量。所讨论的参数(通过多层 shell 逻辑混淆)实际上是GRUB_GFXPAYLOAD_LINUX
供应/etc/default/grub
,该文件旨在由最终用户修改,因此不会在软件包更新后受到影响。
仅当 GRUB_GFXPAYLOAD_LINUX 设置为时,keep
该$vt_handoff
变量才会设置值。根据GNU GRUB 手册虽然 GRUB_GFXPAYLOAD_LINUX 的最常见选择是keep
(您当前的设置)和text
(显然不适合您的用例),但它也可以设置为任何有效值图形模式。这意味着您可以将其更改为auto
,或者更好的是,更改为width✕height
系统 BIOS/EFI 选择的精确默认屏幕分辨率(这相当于keep
),可以通过videoinfo
引导加载程序本身中的命令发现(并且,在大多数情况下,也可以sudo fbset -s
在系统启动后使用终端中的命令发现)。
这样做的好处是可以保持当前启动过程不变除了删除 的值分配$vt_handoff
,尽管在按下 bootloader 菜单项时您仍会在内核命令行末尾看到它,但由于它现在没有值,因此实际上不会传递给内核。您可以在更改 GRUB_GFXPAYLOAD_LINUX 后在终端中输入 并重新启动计算机来e验证是否确实如此。cat /proc/cmdline
最后一步是将 GRUB 最终替换的值恢复$vt_handoff
到内核命令行,这次是在您想要的位置。在上面的第二个代码片段中,我们看到当 GRUB_GFXPAYLOAD_LINUX 设置为时,keep
会$vt_handoff
给出该值vt.handoff=7
,粗体部分是您需要在 中分配给 GRUB_CMDLINE_LINUX_DEFAULT 的其他内核命令行设置前面添加的内容/etc/default/grub
。再次,您可以在进行更改并重新启动后使用 验证一切是否符合预期cat /proc/cmdline
。如果遇到您的问题,我会亲自处理这个问题。
GRUB 定制器
直接编辑/etc/default/grub
文件的另一种方法是安装并使用GRUB 定制器,它以周到的 GUI 布局显示这些相同的变量。如果您在终端中使用最新版本(19.10“Eoan Ermine”或更高版本)的 Ubuntu 或其版本之一(如 Kubuntu),则安装它很简单sudo apt install grub-customizer
。它有一个高级设置对话框(如下所示),其中显示了您需要修改的相同值,/etc/default/grub
并保留了修改文件的备份,以防您以后需要恢复更改。
¹ 需要注意的是,在本文中介绍的整个 GRUB 配置过程中,所有对 $vt_handoff
是变量名本身的实例,而不是更常见的参数扩展/替换各种 *NIX shell 执行的行为。Ubuntu 版本的 GRUB 框架的预期行为是,对它的引用将保留为内核命令行的所有实例中的变量名,包括 grub.cfg
这是初始的最终结果 grub mkconfig
过程和每个后续 update-grub
调用。变量的值也在 GRUB 配置文件中定义,引导加载程序本身在每个引导周期中执行替换。这就是为什么它经常被转义为 \$vt_handoff
在上面的代码片段中,这样可以防止过早地用变量名替换其值。