I used to add another option in the initial grub menu for booting text mode ( init 3 ).
I do that by duplicating the standard option and adding nomodeset plus init 3 to the option menu.
Is it possible to do that with grub 2. I have not found the possibility to duplicate the actual menu option.
I think you would have to write your own script that used one of the menu options and added a 3 to its end. Or, you could modify the recovery setting so it was the same as the main one, but only included adding in a number 3. The file /etc/default/grub contains the entries which you must edit as root. Have a look these two entries:
Consider that after your system is up and running, you seldom need the normal recover line but in any event, you could always just keep a good working LiveCD sitting around should the worst come to pass. I have a couple of bash scripts you might find useful in this.
That is a good example anika200, but the problem I have with it (one of several problems I have on many issues on all sorts of things I am sure lol!) is it really would need to detect the loaded kernels in some way to create a menu item where it only adds a 3. Further, one could remark out the standard line and just use a custom one where you could always return the standard one to use later if you want. And thanks for the kind words concerning my bash scripts.
I guess what I was thinking about was adding a custom menu item to boot a compressed image into memory. Then have something like say fsck run and then reboot when the task is done. Otherwise, I see your point about the kernel versions. Sooo, when can we see this option added to grub2cmd
Well, as you might imagine I have played with grub 2 a lot. Now one thing I was trying to do was to just change the default menu option we just call openSUSE which is always the most recent kernel version you have loaded. The problem I found out is that the file /boot/grub2/grub.cfg is held in a buffer and not written out till the end. The grub 2 script files and custom ones that you might write, can add on to the new file, one by one till the end, but it can’t go backwards and change anything already done. When you look at the file /boot/grub2/grub.cfg you can see that it has a header, the first menu option, the base menu options and anything the os-prober might find. Through the use of numbering added scripts, you can place your own stuff in between each task right to the end. SO, the only options you have is to create a new script, which does work if the number is not used by the base grub. If you make a change to the base scripts, it can be over written with the next grub 2 update. In your example though, it could be possible to create a new entry based on something, but I am not sure how you will communicate to it just what you want. For instance, you could reproduce the latest kernel version just as openSUSE does and then go back and add in a 3. But it would be harder to select anything else without making a change to your script before it gets run. I figured a lot more about how it works, but the best I could on changing the lead kernel version loaded by default, was to modify the /boot/grub2/grub.cfg file after the fact which is easy to do and I even have it automated. But, run just one update to the grub 2 menu and it is all gone. So, I have just been looking around for a way to make changes that do not require a change to the base files that we normally get.
Further, another person here you want to look to on grub 2 is please_try_again who has created some real good stuff. Have a look at this:
That’s correct. But how about writing what you want directly? There is nothing you can’t change here. There are all bash scripts … well unfortunately sh scripts, an “sh” means ‘bash’ under openSUSE but ‘dash’ under Ubuntu. Thus pay attention to posix syntax while taking scripts from Ubuntu or vice-versa (it sucks).
Exactly. And this is why you should use updategrub -a instead of that boring and misleading /usr/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg (updategrub works on UEFI systems as well) . This function can help you do all you want without touching the base scripts:
function alt_linux {
if -f /etc/grub.d/30_os-prober_alt ]; then
case $1 in
on)
if-x /etc/grub.d/10_linux ]; then
cp /etc/grub.d/10_linux{,.org}
chmod 644 /etc/grub.d/10_linux.org
sed -i '/gettext_/s/, with Linux/ - kernel/;s/OS="${GRUB_DISTRIBUTOR} Linux"/OS="${GRUB_DISTRIBUTOR}"/' /etc/grub.d/10_linux
fi
if -x /etc/grub.d/30_os-prober -a -f /etc/grub.d/30_os-prober_alt ] ; then
chmod 644 /etc/grub.d/30_os-prober
chmod 755 /etc/grub.d/30_os-prober_alt
fi
;;
off)
if -f /etc/grub.d/10_linux.org ]; then
mv /etc/grub.d/10_linux{.org,}
chmod 755 /etc/grub.d/10_linux
fi
if -x /etc/grub.d/30_os-prober_alt -a -f /etc/grub.d/30_os-prober ] ; then
if $ALTERNATE -eq 1 ] ; then
chmod 755 /etc/grub.d/30_os-prober
chmod 644 /etc/grub.d/30_os-prober_alt
fi
fi
;;
esac
else
printf "WARNING: /etc/grub.d/30_os-prober_alt not found. Alternate script not used.
"
fi
}
I don’t care about 30_os-prober. I don’t touch it and don’t use it. I use 30_os-prober_alt instead.
I don’t like the way 10_linux name the entries “Linux with bla bla …” So I rename 10_linux and clear the executable bit and source a sligthly modified version instead. When I’m done, I restore the original 10_linux and set the executable bit back. Of course I could also use an alternate 10_linux, like I do with 30_os-prober.
And if one prefer to use the basic scripts (for a change) , he would just type ‘updategrub’ without the option “-a”.
40_custom is the wrong approach here. You use it for static entries, which never change - such as chainloaders. It doesn’t make sense to put kernel boot entries in there, even if they use symlinks, like Ubuntu does. updategrub will add chainloaders for other Legacy or Grub2 it might detect (if there are not already present of course). It also used to add chainloaders for “unsupported” OSes, such as BSDs, but I don’t neee that anymore, since 30_os-prober_alt can write BSD kernel entries (requires os-prober 1.56 from my repo though).
I can understand. I used to do that too … a LOT !!! on dozens on computers. At the beginning, it was only on Ubuntu, because Ubuntu has been using Grub2 for years now. Then Fedora switched to Grub2, and now openSUSE. At some point, I realized that I could not continue to sed, awk or parse however grub.cfg on so many systems.
please_try_again, you got me sold, but the base system is just what you get plus I am not sure I agree with openSUSE dev’s that think our menu system is better off by hiding the many kernel versions by default. One thing is for sure, we need to protest on the next release that the colors you get when you decide to edit the default kernel load options should use your black and white scheme which is so a normal person can read the edit screen. Since you came up with a good fix, you should put it forth as a bug report right now for openSUSE 12.3 M1 if the issue should still exist. And I will second the vote when you make it.
I am using a modified script from /etc/etc/grub.d/10_linux
The problem that I was asked was as follows:
How to add the same option as the default system (Task 3) option to the boot menu, but modifying the boot (Task 4) settings to start text-mode.
The general idea at the beginning was to see how the initial menu generated (task 1), apply this method to add my own option (task 2).
Realization of task 1
The system menu is created by the “10_linux” script located in the /etc/grub.d directory
-) make a backup of the directory /etc/grub.d ( most important )
-) Delete the file /etc/grub.d/40_custom
-) copy the file /etc/grub.d/10_linux ==> /etc/grub.d/40_custom
-) edit the /etc/grub.d/40_custom file and at the 2nd line add the -x option (we then get a line ==> set e x 2)
-) open a terminal
-) look on the screen the generation of the menu. Using the following command. Note the absence of the “-o” option. This point is critical and deserves our attention.
linux:~ # Su /usr/sbin/grub2-mkconfig /boot/grub2/grub.cfg
First we save the contents of the screen in a text file to facilitate a subsequent review.
By examining the log to the screen, we see that:
a) a menu creation script is generated by the script 10_menu. Operations appearing between the tags ### BEGIN /etc/grub.d/10_linux ### and ### END /etc/grub.d/10_linux ###
b) in the middle of the stream of data generated between the tags ### BEGIN /etc/grub.d/40_custom ### and ### END /etc/grub.d/40_custom ###, we recognize the same menu creation code as which one between ### BEGIN /etc/grub.d/10_linux ### and ### END /etc/grub.d/10_linux ###.
Now we will try to understand the generation of the menu by comparing what appears between the tags### BEGIN /etc/grub.d/10_linux ### and ### END /etc/grub.d/10_linux ### and
BEGIN /etc/grub.d/40_custom ### and ### END /etc/grub.d/40_custom
Looking at the 10_menu script code on the screen, helped by the indentation, we notice immediately the creation of the menu :
Realization of task 2
We reboot the system to see what the menu presents.
We notice that the menu option offers 2 choices of starting. One option is showing in his text something easy to find: (recovery mode).
So we finish booting.
We re-open the log file that we had previously backed up. We are looking for the text (recovery mode).
It appears a first time between### BEGIN /etc/grub.d/10_linux ### and ### END /etc/grub.d/10_linux ### We do leave this part.
It then appears between the tags ### BEGIN /etc/grub.d/40_custom ### and ### END /etc/grub.d/40_custom ###
It appears a first time in the “linux_entry” function.
Then we look where this function is called from.
And we find that there are 3 call.
As for the variable $menuentry_id_option which appear in the screen log.
As for the number of selection in the boot menu.
Therefore we will use the first call to the function linux_entry, and we will delete the others.
Realization of task 3
The change to /etc/grub.d/40_custom script.
To maintain consistent line numbers we work from the end of the script to the beginning.
Deleting lines 261 to 265
As we don’t use a submenu, but only a main supplementary option choice, the structure of the script is
menuentry ‘openSUSE’…
$menuentry_id_option… {
…
…
…
}
It is therefore not necessary to insert a closing ‘}’.
Deleting lines 252 to 255
As we don’t use a submenu, but only a main supplementary option choice, there is no need for ‘recovery’ option, we delete the third call to the linux_entry function.
Deleting lines 250-251
As we don’t use a submenu, but only a main supplementary option choice, there is no need for ‘default’ option, we remove the second call to the linux_entry function.
Deleting lines 246-247
AAs we don’t use a submenu, but only a main supplementary option choice, there is no need for printing information text indicating the existence of a submenu.
Deleting line 241
As we don’t use a submenu, the submenu_indentation variable does not have to be modified.
Deleting lines 103-105
We are in the function that writes code that will generate the main menu and submenu options. As we don’t use submenu, but only an main supplementary noption, and as this additional option is not of common use, we will not use the last choice backup functionality.
Realization of Task 4
We will now change the settings for the command that GRUB should run.
As this option can serve when I install a new version of the NVIDIA driver or after upgrading the kernel, which implies a re-installing the NVIDIA driver, I’ll pass the “nomedeset” and “init 3” options.
After Line 240 of the new script,
We add a complement to text indicating that this startup option provides a “Text MODE” mode
We therefore insert :
my_mode="TEXT MODE"
NEW_OS="$ {OS} ${my_mode}"
The amended code becomes:
If "x$ is_first_entry" = xtrue]; thenmy_cmd_default = "init 3" nomodeset
NEW_GRUB_CMDLINE_LINUX_DEFAULT = \
[INDENT=3]"${GRUB_CMDLINE_LINUX_DEFAULT} ${my_cmd_default}"
[/INDENT]
my_mode = "TEXT MODE"
NEW_OS = "${OS} ${my_mode}"
linux_entry "${NEW_OS}" "${version}" single "${GRUB_CMDLINE_LINUX} \
[INDENT=4]${NEW_GRUB_CMDLINE_LINUX_DEFAULT}"
[/INDENT]
If [z "$ boot_device_id"]; then
[INDENT=2]boot_device_id = "$(grub_get_device_id"${GRUB_DEVICE}")"[/INDENT]
fi
fi
Now verify the screen log for /etc/grub.d/40_custom by re-running the command
linux:~ # Su /usr/sbin/grub2-mkconfig /boot/grub2/grub.cfg
If the syntax is correct and if you get no error then compile tje menu by issuing ( don’t forget the -o
linux:~ # Su /usr/sbin/grub2-mkconfig **-o** /boot/grub2/grub.cfg
Please forgive me for grammatical errors, English is not my mother language.
Please also apologize for corner cutting and/or inaccuracies you may find.
I am ready to improve this text as soon as you find it usefull.
The new /etc/grub.d/40_custom script is here :SUSE Paste
This is far too complicated. And you seem to misunderstand the purpose of 40_custom and in some way misuse this script. Here’s an example on how 40_custom is supposed to look like:
#!/bin/sh
**exec tail -n +3 $0
# This file provides an easy way to add custom menu entries. Simply type the
# menu entries you want to add after this comment. Be careful not to change
# the 'exec tail' line above.
**
###Don't change this comment - UpdateGrub2 identifier: Original name: Ubuntu_Grub2_1.99_in_sda###
menuentry "Ubuntu Grub2 1.99 in sda MBR" {
set root=(hd0)
chainloader +1
}
###Don't change this comment - UpdateGrub2 identifier: Original name: openSUSE_Grub2_2.00_in_sdb###
menuentry "openSUSE Grub2 2.00 in sdb MBR" {
set root=(hd1)
chainloader +1
}
###Don't change this comment - UpdateGrub2 identifier: Original name: Fedora_Grub2_1.99_in_sda13###
menuentry "Fedora Grub2 1.99 in sda13" {
set root=(hd0,msdos13)
chainloader +1
}
###Don't change this comment - UpdateGrub2 identifier: Original name: (Mandriva/ArchLinux/Debian)_Legacy_Grub_in_sda15###
menuentry "(Mandriva/ArchLinux/Debian) Legacy Grub in sda15" {
set root=(hd0,msdos15)
chainloader +1
}
###Don't change this comment - UpdateGrub2 identifier: Original name: (Mandriva/ArchLinux/Debian)_Legacy_Grub_in_sdb6###
menuentry "(Mandriva/ArchLinux/Debian) Legacy Grub in sdb6" {
set root=(hd1,msdos6)
chainloader +1
}
menuentry "OpenBSD 4.7" {
set root=(hd0,2)
chainloader +1
}
menuentry "NetBSD 5.0.2" {
set root=(hd0,3,a)
chainloader +1
}
menuentry "FreeBSD 7.2" {
set root=(hd0,3,a)
freebsd /boot/loader
}
menuentry "DragonFly 2.4.1" {
set root=(hd0,2,a)
freebsd /boot/loader
}
menuentry "FreeBSD 8.0 - alt" {
set root=(hd1,3,a)
freebsd /boot/loader
}
menuentry "OpenBSD 4.7 - alt" {
set root=(hd1,2)
chainloader +1
}
menuentry "NetBSD 5.0.2 - alt" {
set root=(hd1,3)
chainloader +1
}
menuentry "DragonFly 2.4.1 - alt" {
set root=(hd1,2,a)
freebsd /boot/loader
}
You should not touch the code in red. In my example, the entries in blue were added automatically by updategrub. The other entries were added manually - actually by another script, but it’s irrelevant. Anyway, how the entries were added doesn’t matter. This “script” is not intended to contain code. If you want to add some code, just add another script starting with number n, where 10 < n < 40. The Grub devs provided a way for users to add static boot entries, and that’s what 40_custom is for, as @anika200 mentioned, except that the example he posted was again a “misuse” of 40_custom (but not as bad as what you’re doing here).
I alreadey understood that what you wanted to achieve was not “Adding options in grub2 menu” but “Adding optional boot entries”. I was about to suggest a solution - which would have required a little bit of programming - but I thought that James’s answer was good enough and would already solve the problem. Actually, to make sure that YaST doesn’t mess up with kernel options, I would also add them to DEFAULT_APPEND and/or FAILSAFE_APPEND in /etc/sysconfig/bootloader, but I’m not sure how YaST combines both. I’m afraid it overwrites the options in /etc/grub/default, because they look the same, and the other way is impossible - Grub2 being not aware of /etc/sysconfig/bootloader, which is openSUSE specific.
IMO, either replacing the failsafe entry with an entry to boot in runlevel 3 or just booting in console mode is the safest and the easiest. The solution doesn’t have to be systematically more complicated than the problem. The code below will change the default runlevel for both sysinit and systemd:
Runlevel=3
# set default runlevel to console
if ! -f /etc/inittab.orig -a -f /etc/inittab ] ; then
echo "- setting default runlevel to $Runlevel (user defined)"
cp /etc/inittab{,.orig}
cat << EOFINITTAB | sed -f - /etc/inittab.orig > /etc/inittab
s|id:5:initdefault:|id:$Runlevel:initdefault:|
EOFINITTAB
ln -sfn /lib/systemd/system/runlevel3.target /etc/systemd/system/default.target
fi
I fail to understand why you need a permanent boot entry with ‘nomodeset’. If you install either nvidia or ati proprietary driver (properly), they will remove KMS from initrd, Thus ‘nomodeset’ will have no effect, and if you need KMS (for Intel, nouveau and some ATI cards with the opensuse driver), you won’t need to touch anything.