Regenerate the GRUB Menu Safely with grub-mkconfig

Running grub-mkconfig straight at /boot/grub/grub.cfg and hoping is how people end up staring at a rescue shell. Generate into a temporary file first, inspect it, then install it at the location your machine actually uses. Allow 10 to 20 minutes including a reboot-free verification.

The examples target the installed grub-common package, version 2.12-1ubuntu7.3, on this machine.

1. Check the installed command

grub-mkconfig assembles a configuration from the settings in /etc/default/grub and the executable scripts in /etc/grub.d. By default it writes the generated text to standard output, or to a file if you pass -o. It does not install GRUB or pick a disk for you.

$ grub-mkconfig --version
grub-mkconfig (GRUB) 2.12-1ubuntu7.3
$ grub-mkconfig --help
Usage: grub-mkconfig [OPTION]
Generate a grub config file

This installed version documents exactly three options: --output=FILE, --help and --version. Do not carry over an option from a different GRUB tool.

2. Inspect the inputs before changing anything

Read the current settings and list the generator scripts. Both are ordinary, unprivileged reads on a typical install:

$ sed -n '1,220p' /etc/default/grub
$ find /etc/grub.d -maxdepth 1 -type f -printf '%f %m\n' | sort

Checkpoint: if you just changed a setting, record the old line or take a backup before proceeding. This creates a dated copy without touching the live file:

$ sudo cp --preserve=all /etc/default/grub /etc/default/grub.before-$(date +%Y%m%d-%H%M%S)

That is the first command in this guide that normally needs elevated privileges.

3. Generate a disposable configuration first

Write to a path in /tmp for the first run. The output file is disposable and the command never touches /boot/grub/grub.cfg on its own:

$ test -d /tmp/grub-check || mkdir /tmp/grub-check
$ sudo grub-mkconfig --output=/tmp/grub-check/grub.cfg
Generating grub configuration file ...
done

The exact messages depend on your generator scripts, so lean on the exit status rather than matching a particular line:

$ printf 'exit status: %s\n' "$?"
exit status: 0
$ test -s /tmp/grub-check/grub.cfg && echo 'generated file is non-empty'
generated file is non-empty

Example: on this machine, running the command without elevated privileges stops with grub-mkconfig: You must run this as root. That is a permission check, not a reason to make the output file world-writable.

4. Inspect the generated entries

Look at the parts that matter for your change: the file header, menu entries, kernel paths, root identifiers, any custom entries. This is read-only inspection:

$ sed -n '1,100p' /tmp/grub-check/grub.cfg
$ grep -nE '^(menuentry|submenu|linux|initrd|search)' /tmp/grub-check/grub.cfg

A non-empty file is not proof every entry is correct. The generator can finish clean while a kernel, chainloader or custom script silently drops the entry you expected. Compare the result against /boot and against the change you intended, and fix any custom script that prints sensitive data or shell errors before you install its output.

For a custom menu item, the usual extension points are /etc/grub.d/40_custom or /boot/grub/custom.cfg, depending on your distribution's layout. Keep the first lines of 40_custom intact, and test a custom entry's paths and recovery route before relying on it: it can be boot-critical.

5. Install the generated configuration

Warning: replacing the active GRUB configuration changes the next boot. A malformed or incomplete file can leave the machine unable to reach its normal menu. Keep the previous file until the new one is tested, and arrange physical or console access before doing this on a remote host.

Identify the configuration path your installation actually uses. A conventional Ubuntu layout puts it at /boot/grub/grub.cfg, but do not assume that for every platform:

$ sudo grub-mkconfig --output=/boot/grub/grub.cfg
Generating grub configuration file ...
done

Check the exit status, then the resulting file:

$ printf 'exit status: %s\n' "$?"
exit status: 0
$ sudo test -s /boot/grub/grub.cfg && echo 'installed file is non-empty'
installed file is non-empty

This command only generates the configuration, it does not run grub-install. Do not follow it with grub-install unless you have a separate, verified reason to install or repair the bootloader itself.

6. Recover from a bad result

If generation fails, the output path may be empty or incomplete. Do not reboot to see what happens. Check the error text, the syntax of /etc/default/grub, permissions on the generator scripts, and any script named in the diagnostic:

$ sudo sh -n /etc/default/grub
$ find /etc/grub.d -maxdepth 1 -type f -executable -print | sort

Recovery: if you already replaced the active file and need it back, restore from a backup made before the change, confirming first that it exists and is a regular file:

$ sudo test -f /boot/grub/grub.cfg.before-change && \
  sudo cp --preserve=all /boot/grub/grub.cfg.before-change /boot/grub/grub.cfg

That restore changes boot configuration again, so check its exit status and keep console access available. With no known-good backup, stop changing files and use your distribution's documented boot-repair procedure from local or rescue media.

Done means