update-grub (Grub 2) (memtest86+) 上的 grub.cfg 中存在语法错误

update-grub (Grub 2) (memtest86+) 上的 grub.cfg 中存在语法错误

当我运行 update-grub 或尝试重新安装它时,出现“语法错误”。

输出有点像这样:

error: syntax error.
error: Incorrect command.
error: syntax error.
error: line no: 262
Syntax errors are detected in generated GRUB config file.
Ensure that there are no errors in /etc/default/grub
and /etc/grub.d/* files or please file a bug report with
/boot/grub/grub.cfg.new file attached.

为什么会发生这种情况?我能做些什么?

背景

Manjaro 更新后,我的系统不再启动。它说“/boot/vmlinuz-316-x86_64找不到文件”。然后“你需要先加载内核”。

然后我从 USB 记忆棒(manjaro live/安装程序磁盘)启动,并按照以下说明进行操作https://wiki.manjaro.org/index.php/Restore_the_GRUB_Bootloader(UEFI 系统)使用 chroot 和 update-grub。事实上,在我收到“此系统不支持 EFI 变量”之后,我第一次注意到“语法错误”问题是在我尝试重新安装 grub 的步骤中。

我想(但不确定)这可能已经持续了一段时间而未被注意到。对 grub.cfg 的任何更新都失败了,但旧的 grub.cfg 仍然“足够好”。但在更新后,vmlinuz 文件被重命名,grub.cfg 引用了旧的、不再存在的 vmlinuz 文件。这就是启动失败的原因。


(我在写这篇文章的时候已经知道答案了。这可能不是一个完整的解释,但这足以让我修复它。我只是想分享结果,以节省其他人的麻烦)

答案1

对我来说,这是一个非常具体的答案,但我想以更一般的方式解释如何解决这个问题。

实际上错误消息中已经包含了很多信息,但对我来说一开始并不明显。

简而言之:

  • 按照 /boot/grub/grub.cfg.new 中的行号进行操作。尝试理解为什么您发现存在语法错误。
  • 按照此文件中的注释操作,该注释指向 /etc/default/grub 或 /etc/grub/* 中的特定文件。
  • 如果是代理脚本,请按照提示找到/etc/grub.d/proxifiedScripts/.

详细的故障排除步骤

在“update-grub”上会/boot/grub/grub.cfg自动创建,基于以下文件数:/etc/default/grub,以及 中的任何文件/etc/grub.d/*

/boot/grub/grub.cfg.new
但是,如果出现语法错误(或者我认为是任何错误),原始文件/boot/grub/grub.cfg不会被覆盖,而是在/boot/grub/grub.cfg.new.

错误消息包含引用该文件的行号(在我的例子中为 262)/boot/grub/grub.cfg.new。就我而言,这是 262。查看该文件,我发现:

### BEGIN /etc/grub.d/60_memtest86+_proxy ###
if [ "${grub_platform}" == "pc" ]; then
fi
### END /etc/grub.d/60_memtest86+_proxy ###

我了解到 shell 脚本中不允许使用空的 if/then/fi 块,所以这是语法错误。在我看来,这是相当愚蠢的语言设计,但事实就是这样。

我还找到了一个修复方法,就是在块中添加一条无意义的语句。建议使用冒号,但可能还有其他解决方案。

### BEGIN /etc/grub.d/60_memtest86+_proxy ###
if [ "${grub_platform}" == "pc" ]; then
    :
fi
### END /etc/grub.d/60_memtest86+_proxy ###

更好的办法是完全删除这个无意义的块。

现在我们真的不想手动编辑这个文件,因为更改将在下一次 update-grub 时被擦除(如果成功,这就是目标)。

/etc/grub.d/*
该代码片段包含下一步查看位置的提示:/etc/grub.d/60_memtest86+_proxy。这个文件说:

#!/bin/sh
#THIS IS A GRUB PROXY SCRIPT
'/etc/grub.d/proxifiedScripts/memtest86+' | /etc/grub.d/bin/grubcfg_proxy "+*
+#text
-'Memory Tester (memtest86+)'~30b99791e52c3f0cb32601c5b8f57cc7~
"

/etc/grub.d/proxifiedScripts/*
的相关部分/etc/grub.d/proxifiedScripts/memtest86+是这样的:

    [..]
    cat << EOF
if [ "\${grub_platform}" == "pc" ]; then
    menuentry "Memory Tester (memtest86+)" ${CLASS} {
        search --fs-uuid --no-floppy --set=root ${_GRUB_MEMTEST_HINTS_STRING} ${_GRUB_MEMTEST_FS_UUID}
        linux16 ${_GRUB_MEMTEST_REL_PATH} ${GRUB_CMDLINE_MEMTEST86}
    }
fi
EOF
[..]

该文件本身是一个 shell 脚本,但它有那些“cat”语句。这些打印 shell 脚本片段,最终应进入/boot/grub/grub.cfg.也许经过一些修改。

在 中/boot/grub/grub.cfg.new,我们观察到“menuentry ...”内容实际上丢失了,取而代之的是我们得到一个空的 then..fi 块。为什么“菜单项...”消失了,我不知道。也许grub认为不需要。不幸的是,删除破坏了脚本。

解决方法

技巧/解决方法是在此文件中添加一个冒号,如下所示:

if [ "\${grub_platform}" == "pc" ]; then
    :
    menuentry "Memory Tester (memtest86+)" ${CLASS} {
        search --fs-uuid --no-floppy --set=root ${_GRUB_MEMTEST_HINTS_STRING} ${_GRUB_MEMTEST_FS_UUID}
        linux16 ${_GRUB_MEMTEST_REL_PATH} ${GRUB_CMDLINE_MEMTEST86}
    }

运行 update-grub 时,会生成grub.cfg具有上述解决方法的文件。

背景/更多调查

我系统上的文件夹/etc/grub.d/实际上包含 memtest86+_proxy:60_memtest86+_proxy62_memtest86+_proxy.我认为其中之一是某种剩余物。但它们都有相同的更新时间戳,所以我真的不知道它们中的哪一个可以安全删除。差异显示了这一点:

--- /etc/grub.d/60_memtest86+_proxy 2015-01-08 15:54:02.228927526 +0100
+++ /etc/grub.d/62_memtest86+_proxy 2015-01-08 15:54:02.228927526 +0100
@@ -1,6 +1,6 @@
 #!/bin/sh
 #THIS IS A GRUB PROXY SCRIPT
-'/etc/grub.d/proxifiedScripts/memtest86+' | /etc/grub.d/bin/grubcfg_proxy "+*
-+#text
--'Memory Tester (memtest86+)'~30b99791e52c3f0cb32601c5b8f57cc7~
+'/etc/grub.d/proxifiedScripts/memtest86+' | /etc/grub.d/bin/grubcfg_proxy "+'Memory Tester (memtest86+)'~30b99791e52c3f0cb32601c5b8f57cc7~
+-*
+-#text
 "
\ No newline at end of file

因此,这两个文件都引用相同的代理脚本,但结果通过 grubcfg_proxy 二进制文件通过管道传输,具有不同的参数。这些不同的参数可能负责在60_memtest86+_proxy.

结论

其他人可能有完全不同的问题。但故障排除,至少是第一步,应该非常相似。

答案2

来自 @donquixote 的出色故障排除步骤(+1 赞成)。

对于我的情况,错误是因为当我为 Windows/Ubuntu 双启动设置重新排序菜单选项时,我没有设置 Ubuntu 的启动/分区。

对我有帮助的是在 grub-customizer 菜单中的列表中上下移动菜单选项,并观察 id 语法错误的行号发生了变化,这样,人们就会知道该选项需要进一步关注。

答案3

谢谢它确实对我有帮助。

就我而言,就是那个文件/etc/grub.d/proxifiedScripts/custom

我尝试创建自定义脚本,用于grub-customizer从根路径中的目录启动 Prime OS。

我删除了该文件,然后命令update-grub完成,没有错误,然后我使用重新生成了自定义脚本grub-customizer,并且运行良好。

答案4

用户,我是一个普通的linux新手,但它正在一天天变强。仍在学习一些新命令,但我很快就会掌握 Linux。

根据您的问题和提供的答案,您一定已经解决了问题,但我仍然会对此发表自己的看法。

根据互联网上的一些消息来源,我尝试了所有这些方法,因为我在删除(清除)旧的 Kali 内核时也遇到了这个问题,但没有一个证明可以解决我的问题。

我诉诸于使用我自己的 Linux 知识,瞧!我找到了解决方案。每次我执行“update-grub”时都会产生以下结果, https://im.ge/i/9MH08 然后我检查了 /boot/grub/grub.cfg.new ,错误行是 260,所以首先我在终端中进行了操作;

nano /boot/grub/grub.cfg.new 然后我按下Ctrl</kbd+Shift</kbd+_并输入错误行号(我的是260)

我看到有一个菜单条目给出了错误,但我无法弄清楚问题是什么。我删除了整个菜单项并运行“update-grub”,但 grub 配置文件是只读的,因此我的更改没有影响。

再次有消息来源告诉我,在“update-grub”期间,原始的 grub.cfg 保持不变,但创建了一个新的 grub.cfg.new,所以然后我看到了 grub.cfg(它太只读了。)其中包含原始的东西没有任何错误或菜单项,因此对于每一行或任何错误,这个解决方案 100% 都可以工作。

只需启动一个终端 非 root 用户:首先执行sudo su,然后转到解决方案 根用户:直接转到解决方案 解决方案:

  1. 我通过以下方式删除了(不完全,只是备份)文件 grub.cfg.new:

    mv /boot/grub/grub.cfg.new /home/grub.cfg.new.bak

  2. 然后我将原来的 grub.cfg 替换为 grub.cfg.new:

    mv /boot/grub/grub.cfg /boot/grub/grub.cfg.new

这将用新的替换原来的,因为新的已经备份到目录“/home”并从“/boot/grub/”目录中删除。

  1. 然后我在终端中运行“update-grub”并得到: https://im.ge/i/9QnRx

每个人都可以尝试这个简单的解决方案

相关内容