创建用于运行 systemd multiuser.target 的 debian grub 自定义条目

创建用于运行 systemd multiuser.target 的 debian grub 自定义条目

我有 Debian Stretch,我想要一个自定义 grub 条目,以便在没有图形桌面的情况下运行系统。我认为这就像运行不同的运行级别一样简单,但是阅读相关内容后,我意识到systemd一切都是不同的。

看完之后这个问题关于红帽以及这个其他对于Debian Jessie,我了解了systemd目标,我认为我想做的是在multi-user.target中运行。

我发现了这个软呢帽链接,这个 archlinux 内核链接和另一个。他们都解释说,有一个选项“systemd.unit”可以附加到 grub 菜单项的“linux”行中。因此,我搜索了链接来解释如何创建自定义菜单条目:这个。但是,在 grub 屏幕中查看我自己的带有“e”键的自动 grub 条目,它们比链接中的条目更复杂。问题是我不知道是否必须复制自定义菜单条目中的所有内容。

 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

这是我为最后一个内核自动创建的条目。我可以简单地将所有这些复制到自定义菜单条目中并仅更改

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

线为

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

答案1

经过几天的研究,我有 3 种方法来解决创建自定义条目以运行 Debian 的问题,Systemd而无需从Grub.我认为最好的方法是1。

1.新建/etc/grub.d/*配置文件

为此,我复制了/etc/grub.d/10_linux文件作为模板:

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

原始文件创建最新内核的根条目以及“高级选项”子菜单。因此,我对11_multiuser文件进行了一些编辑,只是为了为多用户选项创建一个新的子菜单,并在多用户模式下为每个内核创建一个新选项。在这里,我将添加一个带有修改后的行的补丁:

--- /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

使用此解决方案,如果我添加/删除内核,或执行某些涉及 grub 菜单重新配置的操作,我所需的多用户条目将自动为每个内核添加。另外,我认为(但不完全确定)如果我更新 grub,我的新配置文件11_multiuser将不会被删除,因为它不是 Grub 预定义配置文件的一部分。

2.修改/etc/grub.d/10_linux文件

这是另一种方法,但我认为这比第一种方法更糟糕。这样,您正在修改官方文件,因此您可能会破坏Grub的配置和整个系统的启动。此外,如果任何更新导致文件替换,您可能会丢失配置。这样做只有一个优点:您可以在“高级选项”子菜单中插入多用户条目。为第一种方法添加的补丁对此部分有效。无论如何,我完全不同意这种做法。

3.修改/etc/grub.d/40_custom文件

该文件旨在插入特定条目。您可以复制该条目/boot/grub/grub.cfg并将其粘贴到此文件中,添加 systemd.. 这完全没问题,但问题是您必须为您想要的每个内核执行此操作。此外,当向系统中删除/添加新内核时,您必须手动维护此文件。另外,这些条目出现在 grub 菜单的末尾,如果您有其他操作系统(例如 Windows),那么您的自定义条目将与第一个 Linux 条目分开。

答案2

由于距您最初发表帖子已有五年了,似乎是时候提出另一个答案了。

如果您(或其他人)不需要包含旧内核的自定义菜单条目,即将推出的解决方案...

  • 避免代码修改
  • 采用静态菜单项,无论系统更新或重建 grub.cfg,它始终反映最新的内核
  • 应出现在 grub 菜单中默认菜单项之后、其他操作系统之前

由于以前从未使用过 Debian,所以这一点并不确定,但只要 Debian 提供了最新内核和 initrd 的通用命名符号链接,如果相应地同化,这应该可以工作。如果 Debian 没有给你这样的符号链接,那么你需要一个在关闭时作为服务运行的脚本,它根据需要执行此操作并应用当前内核和 initrd 的实际名称,或者生成通用符号链接。

在 openSUSE 中,这就是在没有服务的情况下完成的方法,因为 /boot/vmlinuz 和 /boot/initrd 分别是最新内核和 initrd 的符号链接...

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

重新启动并查看。

相关信息在这里,如果有兴趣...
https://forums.opensuse.org/showthread.php/480353-12-2-New-install-Adding-options-in-grub2-menu
https://help.ubuntu.com/community/Grub2/CustomMenus

相关内容