3

I have Debian Stretch and I would like to have a custom grub entry in order to run the system without a graphical desktop. I thought that would be as easy as running a different runlevel, but reading about that, I was aware that, in systemd everything is different.

After reading this question about Red Hat and also this other for Debian Jessie, I learnt about systemd targets, and I think that what I want to do is running in multi-user.target.

I've found this fedora link, this archlinux kernel link and this other one. All them explain that there is one option "systemd.unit" that can be appended in the "linux" line in the grub menu entry. So, I searched for links to explain how to create a custom menu entry: this one. But, looking my own automatic grub entries with the key 'e' in the grub screen, they are more complex than the one in the link. The problem is that I don't know if I must copy all that stuff in the custom menu entry.

 setparams 'Debian gnu/linux, con linux 4.8.0-2-amd64'
 load_video
 insmod gzio
 if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
 insmod part-msdos
 insmod ext2
 set root='hd0,msdos5'
 if [ x$feature_platform_search_hint = xy ]; then
    search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos5 --hint-efi=hd0,msdos5 --hint-baremetal=ahci0,msdos5  3202c741-ef05-40e4-9368-8617e7b1fb3c
else
    search --no-floppy --fs-uuid --set=root 3202c741-ef05-40e4-9368-8617e7b1fb3c
fi
echo 'Cargando Linux 4.8...'
linux /vmlinuz-4.8.0-2-amd64 root=UUID=17f74892-fe09-46ec-91ca-2dca457565a1 ro quiet
echo 'Cargando imagen de memoria inicial...'
initrd /initrd.img-4.8.0-2-amd64

This is my automatically created entry for my last kernel. Can I simply copy all this in a custom menu entry and change only the

linux /vmlinuz-4.8.0-2-amd64 root=UUID=17f74892-fe09-46ec-91ca-2dca457565a1 ro quiet

line to be

linux /vmlinuz-4.8.0-2-amd64 root=UUID=17f74892-fe09-46ec-91ca-2dca457565a1 ro quiet systemd.unit=multi-user.target

?

2 Answers2

1

After some days of researching, I have 3 approaches to the problem of creating custom entries for running a Systemd Debian without graphical desktop from the Grub. I think that the best approach is 1.

1. Creating a new /etc/grub.d/* configuration file

To do that, i copied /etc/grub.d/10_linux file as a template:

sudo cp /etc/grub.d/10_linux /etc/grub.d/11_multiuser

The original file creates the root entry for the latest kernel and also the "Advanced options" submenu. So, I edited my 11_multiuser file a little bit, just to create a new submenu for the multiuser options, and create inside a new option for each kernel, for the multiuser mode. Here I'll add a patch with the modified lines:

--- /etc/grub.d/10_linux
+++ /etc/grub.d/11_multiuser
@@ -118,6 +118,8 @@
       case $type in
      recovery)
          title="$(gettext_printf "%s, with Linux %s (%s)" "${os}" "${version}" "$(gettext "${GRUB_RECOVERY_TITLE}")")" ;;
+      multiuser)
+          title="$(gettext_printf "%s, with Linux %s (multiuser)" "${os}" "${version}")" ;;
      init-*)
          title="$(gettext_printf "%s, with Linux %s (%s)" "${os}" "${version}" "${type#init-}")" ;;
      *)
@@ -227,57 +229,18 @@
 boot_device_id=
 title_correction_code=

-cat << 'EOF'
-function gfxmode {
-   set gfxpayload="${1}"
-EOF
-if [ "$vt_handoff" = 1 ]; then
-  cat << 'EOF'
-   if [ "${1}" = "keep" ]; then
-       set vt_handoff=vt.handoff=7
-   else
-       set vt_handoff=
-   fi
-EOF
-fi
-cat << EOF
-}
-EOF
-
-# Use ELILO's generic "efifb" when it's known to be available.
-# FIXME: We need an interface to select vesafb in case efifb can't be used.
-if [ "x$GRUB_GFXPAYLOAD_LINUX" != x ] || [ "$gfxpayload_dynamic" = 0 ]; then
-  echo "set linux_gfx_mode=$GRUB_GFXPAYLOAD_LINUX"
-else
-  cat << EOF
-if [ "\${recordfail}" != 1 ]; then
-  if [ -e \${prefix}/gfxblacklist.txt ]; then
-    if hwmatch \${prefix}/gfxblacklist.txt 3; then
-      if [ \${match} = 0 ]; then
-        set linux_gfx_mode=keep
-      else
-        set linux_gfx_mode=text
-      fi
-    else
-      set linux_gfx_mode=text
-    fi
-  else
-    set linux_gfx_mode=keep
-  fi
-else
-  set linux_gfx_mode=text
-fi
-EOF
-fi
-cat << EOF
-export linux_gfx_mode
-EOF
-
 # Extra indentation to add to menu entries in a submenu. We're not in a submenu
 # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
 submenu_indentation=""

-is_top_level=true
+# para el menu de multiuser
+submenu_indentation="$grub_tab"
+if [ -z "$boot_device_id" ]; then
+  boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
+fi
+gettext_printf "Agregando entradas multiuser...\n" >&2
+echo "submenu '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote) (MultiUser)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"
+is_top_level=false
 while [ "x$list" != "x" ] ; do
   linux=`version_find_latest $list`
   case $linux in
@@ -331,34 +294,9 @@
     linux_root_device_thisversion=${GRUB_DEVICE}
   fi

-  if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
-    linux_entry "${OS}" "${version}" simple \
-    "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
-
-    submenu_indentation="$grub_tab"
-    
-    if [ -z "$boot_device_id" ]; then
-   boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
-    fi
-    # TRANSLATORS: %s is replaced with an OS name
-    echo "submenu '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"
-    is_top_level=false
-  fi
-
-  linux_entry "${OS}" "${version}" advanced \
-              "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
-
-  for supported_init in ${SUPPORTED_INITS}; do
-    init_path="${supported_init#*:}"
-    if [ -x "${init_path}" ] && [ "$(readlink -f /sbin/init)" != "${init_path}" ]; then
-      linux_entry "${OS}" "${version}" "init-${supported_init%%:*}" \
-         "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} init=${init_path}"
-    fi
-  done
-  if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
-    linux_entry "${OS}" "${version}" recovery \
-                "${GRUB_CMDLINE_LINUX_RECOVERY} ${GRUB_CMDLINE_LINUX}"
-  fi
+  linux_entry "${OS}" "${version}" multiuser \
+              "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} systemd.unit=multi-user.target"
+

   list=`echo $list | tr ' ' '\n' | fgrep -vx "$linux" | tr '\n' ' '`
 done

With this solution, if I add/remove kernels, or perform some action that involves any reconfiguration of the grub menu, my desired multiuser entries will be automatically added for each kernel. Also, I think (but not completely sure) that, if i update the grub, my new configuration file 11_multiuser won't be removed, given that it's not part of the Grub's predefined configuration files.

2. Modifying /etc/grub.d/10_linux file

This is another approach, but i think this is worse than the first one. This way, you are modifying the official file, so you could break the Grub's configuration and the whole system startup. Also, if any update leads to the file replacement, you could loose your configuration. There is only one advantage on doing this: you could insert your multiuser entries in the "Advanced options" submenu.The patch added for the first approach is partially valid for this. Anyway, I totally disagree this approach.

3. Modifying /etc/grub.d/40_custom file

This file is intended to insert specific entries. You could copy the entry from /boot/grub/grub.cfg and paste it in this file adding the systemd.. It is perfectly ok, but the problem is that you must do it for every kernel you want. Also, when removing/adding new kernels to the system, you must maintain this file manually. Plus, these entries appears at the end of the grub menu, and if you have other operating systems like Windows, then your custom entries will be separated from the first Linux entries.

0

As it's five years to the day since your original post, it seems time for another answer.

If you (or someone else) don't require including custom menu entries for old kernels, the upcoming solution...

  • avoids the code mods
  • employs static menu entries which always reflect the latest kernel, regardless of system updates, or rebuilding grub.cfg
  • should appear in the grub menu after the default menu entries, but prior to other OSes

Having never used Debian before, this isn't certain, but as long as Debian provides generically named symlinks to the latest kernel and initrd, this should work if assimilated accordingly. If Debian does not give you such symlinks, then you'll need a script that runs as a service at shutdown, that does this as needed and applies the actual name of the current kernel and initrd, or instead generates the generic symlinks.

This is how it is done without a service, in openSUSE, as /boot/vmlinuz and /boot/initrd are symlinks to latest kernel and initrd respectively...

sudo cp --preserve /etc/grub.d/40_custom /etc/grub.d/25_custom

locate and copy the entirety of relevant menu entries from grub.cfg, to 25_custom

sudo vim /boot/grub2/grub.cfg /etc/grub.d/25_custom

mod menu entries in 25_custom as needed, and retain all lines unless good reason to delete any

and do the following mods so entries no longer depend on specifically named kernel

mod line like this...

echo 'Loading Linux 5.16.4-1-default ...'

...to be like this

echo 'Loading Linux ...'

mod line like this...

linux /boot/vmlinuz-5.16.4-1-default ...

...to be like this. the '3' is for multi-user in openSUSE

linux /boot/vmlinuz ... 3

mod line like this...

initrd /boot/initrd-5.16.4-1-default

...to be like this

initrd /boot/initrd

sudo grub2-mkconfig -o /boot/grub2/grub.cfg

reboot and take a look.

related info here, if interested...
https://forums.opensuse.org/showthread.php/480353-12-2-New-install-Adding-options-in-grub2-menu
https://help.ubuntu.com/community/Grub2/CustomMenus

S Kos
  • 1