54

I have Ubuntu 10.10 Server installed on a single-board machine in a semi-embedded environment; no keyboard or screen, just SSH access to it.

So it's really frustrating when it occasionally boots up and gets stuck on the GRUB menu, waiting for a keystroke to select the first option.

How do I configure GRUB to under no circumstances wait for a keystroke?

Update #1: There is no menu.lst, since this is GRUB 2. But I do have an /etc/default/grub which is like so:

GRUB_DEFAULT=0
#GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=2
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX=""

Update #2: I figured it out. On boots which follow unsuccessful boots, GRUB disables its own timeout. Since showing the menu makes a boot unsuccessful, this is an inescapable loop. This behaviour may be disabled by editing the /etc/grub.d/00_header file, and changing the make_timeout function:

make_timeout ()
{
    echo "set timeout=0"
}

Now exit and re-run the grub configuration updater script:

sudo update-grub2

It makes no sense to me that this behaviour would be the default for Ubuntu Server, a product intended for machines accessed by console.

mikepurvis
  • 1,047

7 Answers7

41

For Ubuntu 12.04 LTS there is a specific option that can be set in /etc/default/grub.

For example, if you want to have a 2 seconds timeout (thus avoiding hangs for unattended reboots) just add the following line in /etc/default/grub:

GRUB_RECORDFAIL_TIMEOUT=2

Remember to run update-grub after that...

18

Here are instructions for Ubuntu 10.10, which are slightly different from prior versions. In file /etc/grub.d/00_header comment out the stupid check for a prior boot failure:

##if [ \${recordfail} = 1 ]; then
##  set timeout=-1
##else
  set timeout=${2}
##fi

Then update:

sudo update-grub

Be aware that if there is a second drive with Linux attached, grub2 will find it, and ask you at boot which one you want. Remove all extra drives before running "update-grub".

See also https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/797544

Bryce
  • 561
  • 1
  • 5
  • 13
6

I came across this deeply unpleasant design oversight with Ubuntu Server 9.10. Your fix has helped me enormously. I just wanted to point out that the fix needed for 9.10 is different as there is no "make_timeout ()" function in the same file.

For Ubuntu 9.10, go to the end of the same file (00_header) and change the following:

if [ \${recordfail} = 1 ]; then
  set timeout=-1
else
  set timeout=${GRUB_TIMEOUT}
fi
EOF

to

if [ \${recordfail} = 1 ]; then
  set timeout=${GRUB_TIMEOUT}
else
  set timeout=${GRUB_TIMEOUT}
fi
EOF

As before, then run:

sudo update-grub2
GNTC
  • 61
1

Configure GRUB for serial access (and your bootloader, while you are at it) and keep an open serial port, null-modem cable, and USB-to-RS232 converter handy for these instances. I run a headless server and a Guruplug and wouldn't have it any other way.

LawrenceC
  • 1,262
1

I just set a long timeout for recordfail:

if [ "\${recordfail}" = 1 ]; then
  set timeout=30
else
  set timeout=${2}

Meaning you get 30 sec timeout when you boot, if the previous boot failed. (Not unlike how that other OS does it...)

This could (and IMHO should) even be a setting right there in /etc/default/grub.

1

I really don't know why this is the default action, especially for a server, but this is what I have implemented in my server setup scripts.

sudo sed -i 's/set timeout=-1/set timeout=30/g' /etc/grub.d/00_header
sudo update-grub
1

This approach is a bit cleaner - just modify /etc/default/grub to add the line:

GRUB_RECORDFAIL_TIMEOUT=2

...which one might do automatically with something like this in provisioning:

if grep '^GRUB_RECORDFAIL_TIMEOUT=' /etc/default/grub ; then
   echo GOOD: /etc/default/grub
else
   echo FIXING: /etc/default/grub
   perl -pi.bak -e \
      's/^(GRUB_TIMEOUT=.*\n)/${1}GRUB_RECORDFAIL_TIMEOUT=2\n/' \
      /etc/default/grub
   update-grub
fi

This should be viable if the variable GRUB_RECORDFAIL_TIMEOUT is mentioned in /etc/grub.d/00_header (as I'm seeing in 12.04 LTS) in:

make_timeout ()
{
    cat << EOF
if [ "\${recordfail}" = 1 ]; then
  set timeout=${GRUB_RECORDFAIL_TIMEOUT:--1}
else
  set timeout=${2}
fi
EOF
}

I'm a bit curious about whether digging into how the failures are recorded might yield an even better answer.