For me it was a very specific answer, but I want to explain in a more general way how to troubleshoot this.
Actually a lot of the information is already in the error message, but to me it was not obvious at first.
In short:
- Follow the line number, in /boot/grub/grub.cfg.new. Try to understand why what you find there is a syntax error.
- Follow the comment in this file, that points to either /etc/default/grub, or a specific file in /etc/grub/*.
- In case of a proxy script, follow the hint to a file in
/etc/grub.d/proxifiedScripts/.
Troubleshooting steps, in detail
The /boot/grub/grub.cfg is automatically created on "update-grub", based on a number of files: /etc/default/grub, and any files in /etc/grub.d/*.
/boot/grub/grub.cfg.new
However, in case of a syntax error (or any error, I suppose), the original /boot/grub/grub.cfg is NOT overwritten, but instead the new file is created in /boot/grub/grub.cfg.new.
The error message contains a line number, in my case 262, that refers to this /boot/grub/grub.cfg.new file. In my case, this was 262. Looking at the file, I found this:
### BEGIN /etc/grub.d/60_memtest86+_proxy ###
if [ "${grub_platform}" == "pc" ]; then
fi
### END /etc/grub.d/60_memtest86+_proxy ###
I learned that en empty if/then/fi block in shell script is not allowed, so this was the syntax error. Quite stupid language design imo, but this is how it is.
I also found a fix, which is to add a meaningless statement in the block. A colon was suggested, but there might be other solutions.
### BEGIN /etc/grub.d/60_memtest86+_proxy ###
if [ "${grub_platform}" == "pc" ]; then
:
fi
### END /etc/grub.d/60_memtest86+_proxy ###
Even better would be to remove this meaningless block completely.
Now we don't really want to edit this file manually, because the changes would be wiped on the next update-grub (if successful, which is the goal).
/etc/grub.d/*
The snippet contains a hint where to look next: /etc/grub.d/60_memtest86+_proxy. This file says:
#!/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/*
The relevant part of /etc/grub.d/proxifiedScripts/memtest86+ is this:
[..]
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
[..]
The file itself is a shell script, but then it has those "cat" statements. These print the shell script snippets that should finally go into /boot/grub/grub.cfg. With some modifications, maybe.
In the /boot/grub/grub.cfg.new, we observe that the "menuentry ..." stuff is actually missing, and instead we get an empty then..fi block. Why the "menuentry ..." disappears, I don't know. Maybe grub thinks that it is not needed. Unfortunately, the removal breaks the script.
Workaround
The trick / workaround was to add a colon in this file, like this:
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}
}
When running update-grub, this generates a grub.cfg with the workaround described above.
Background / More investigation
The /etc/grub.d/ folder on my system actually contained two files for memtest86+_proxy: 60_memtest86+_proxy and 62_memtest86+_proxy. I assume that one of them is a leftover of some sort. But both of them have the same updated timestamp, so I really don't know which of them would be safe to delete. A diff shows this:
--- /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
So, both of the files refer to the same proxified script, but the result is piped through the grubcfg_proxy binary, with different parameters. These different parameters could be responsible for removing the "menuentry ..." stuff in case of the 60_memtest86+_proxy.
Conclusion
Others may have completely different problems. But the troubleshooting, at least the first steps, should be quite similar.