![update-grub (Grub 2) (memtest86+) 上的 grub.cfg 中存在语法错误](https://linux22.com/image/66853/update-grub%20(Grub%202)%20(memtest86%2B)%20%E4%B8%8A%E7%9A%84%20grub.cfg%20%E4%B8%AD%E5%AD%98%E5%9C%A8%E8%AF%AD%E6%B3%95%E9%94%99%E8%AF%AF.png)
当我运行 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+_proxy
和62_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
,然后转到解决方案 根用户:直接转到解决方案 解决方案:
我通过以下方式删除了(不完全,只是备份)文件 grub.cfg.new:
mv /boot/grub/grub.cfg.new /home/grub.cfg.new.bak
然后我将原来的 grub.cfg 替换为 grub.cfg.new:
mv /boot/grub/grub.cfg /boot/grub/grub.cfg.new
这将用新的替换原来的,因为新的已经备份到目录“/home”并从“/boot/grub/”目录中删除。
- 然后我在终端中运行“update-grub”并得到: https://im.ge/i/9QnRx
每个人都可以尝试这个简单的解决方案