Check GRUB Configuration Syntax Before You Reboot

A typo in grub.cfg is the kind of mistake you only find at the next boot. grub-script-check parses a GRUB script before you rely on it, so you catch that typo now. This guide checks a real grub.cfg, shows a harmless scratch file, explains the output that matters, and separates syntax checking from the tests this command cannot perform.

Time: about five minutes for one file. You need a shell and the GRUB tools from the grub-common package. The examples were run with GRUB 2.12-1ubuntu7.3 on Ubuntu. The command does not modify its input, so the normal check needs no elevated privileges. Reading a protected file may require sudo.

Before you start

grub-script-check checks a GRUB script for syntax errors. It is similar in purpose to sh -n, but it is a GRUB parser, not a POSIX shell parser. It does not regenerate configuration, install a boot loader, repair a missing kernel, or prove that every referenced path and module will work at boot.

On a typical installed system, /boot/grub/grub.cfg is generated configuration: do not hand-edit it as part of this check. If you changed a generator input or a script under /etc/grub.d, generate a new candidate through your normal GRUB workflow, then check the resulting file before rebooting.

1. Check the installed configuration

Start with the file that the firmware path will normally hand to GRUB:

grub-script-check /boot/grub/grub.cfg

A successful run prints nothing and returns exit status zero. Make the status visible when you are writing a shell script or want an explicit checkpoint:

if grub-script-check /boot/grub/grub.cfg; then
    echo "GRUB syntax check passed"
else
    echo "GRUB syntax check failed" &2
    exit 1
fi

On a machine where your account cannot read the file, repeat the read-only check with elevation:

sudo grub-script-check /boot/grub/grub.cfg

Checkpoint: a blank output is success only when the exit status is zero. Do not treat silence from a command in a longer pipeline as proof unless you inspect its status.

2. Check a candidate file without changing the system

For a configuration you have generated or copied for review, pass its path as the final argument. This example uses a complete, small GRUB script and leaves the installed boot configuration alone:

cat > /tmp/example-grub.cfg <<'EOF'
set timeout=5
menuentry 'Example Linux' {
    linux /vmlinuz root=/dev/sda1 ro
    initrd /initrd.img
}
EOF

grub-script-check /tmp/example-grub.cfg
echo "exit status: $?"

The expected result is:

exit status: 0

The paths in this deliberately small example are syntax values, not a recommendation for your machine: replace them with values from the system you are actually configuring. The checker parses the structure; it does not confirm that /vmlinuz, /initrd.img, or the specified root device exists.

3. Read a failure as a parser error

Remove the closing brace from the example and run the check again:

sed '/^}$/d' /tmp/example-grub.cfg > /tmp/broken-grub.cfg
grub-script-check /tmp/broken-grub.cfg
echo "exit status: $?"

With the installed GRUB 2.12 build, this reports errors including:

error: out of memory.
error: syntax error.
error: Incorrect command.
error: syntax error.
Syntax error at line 3

The wording is not a clean explanation of the missing brace, and some messages can look unrelated. What actually matters: the command returned status 1 and pointed at a line near the parser's failure. Inspect that line and the surrounding block, because an earlier missing quote, brace, or command terminator can make the reported location appear late.

After correcting the candidate, rerun the same command:

grub-script-check /tmp/example-grub.cfg && echo "syntax is valid"

Do not overwrite /boot/grub/grub.cfg merely to make the check pass. Keep the broken candidate so you can compare the correction, then use your distribution's documented configuration-generation process once the source change is understood.

4. Use standard input for a pipeline

The path argument is optional. With no path, the command reads the script from standard input, which is useful when a generator writes to standard output or when you want to inspect a transformed copy:

grub-mkconfig 2>/tmp/grub-mkconfig-errors \
  | grub-script-check
status=\${PIPESTATUS[0]}
check_status=\${PIPESTATUS[1]}

if [ "\$status" -ne 0 ]; then
    echo "grub-mkconfig failed; read /tmp/grub-mkconfig-errors" >&2
    exit "\$status"
fi
exit "\$check_status"

This pipeline needs care. The checker only sees the generated text, and a producer failure can otherwise be hidden by ordinary pipeline status rules. The Bash PIPESTATUS array above preserves both results. The command writes the generator's diagnostic file under /tmp; remove it once you have finished reviewing it.

If you only need to check a known file through standard input, this is simpler:

grub-script-check < /tmp/example-grub.cfg

5. Turn on verbose output when comparing input

The -v and --verbose options print each input line after it is read. They earn their keep when a pipeline or generated file is not the text you expected:

grub-script-check --verbose /tmp/example-grub.cfg

For the example file, the command prints its five lines and still exits zero. Verbose output is an echo of the input, not a deeper semantic or bootability test. Avoid pasting verbose output into tickets if the configuration contains host-specific paths or other information you do not want to disclose.

What this check does not prove

Use the command as a gate before a reboot, then check the paths and boot assumptions separately. A syntax pass is necessary, but it is only one part of a reliable boot change.

Options and version check

The installed GRUB 2.12 command also accepts --help, --usage, and --version. Confirm the binary and version when comparing a report from another host:

command -v grub-script-check
grub-script-check --version

On the system used for these examples, the version output is:

grub-script-check (GRUB) 2.12-1ubuntu7.3

Option text and diagnostic details can differ between GRUB builds. When a failure is surprising, record the version, the exact input, the exit status, and the non-verbose output before changing anything else.

Done means