You are not logged in.

#1 2012-03-08 00:26:57

OakRaider4Life
Member
Registered: 2012-02-08
Posts: 98

Runlevels on GRUB2

I recently changed my bootloader to GRUB2, which is both more convenient and a little more difficult. It's convenient because it make OS detection a breeze, and makes my life very easy. However, I want to be able to have two GRUB menu entries for Arch, one which runs it in runlevel 3 and one which runs it in runlevel 5. I know that in grub legacy, I could have accomplished this by simply adding two separate entries to the menu.lst file. Since that file doesn't exist in GRUB2, I'm looking for a way to setup the 2 separate menu entries, preferably so they won't be overwritten everytime there's a kernel update. Can anyone help me with this?

Offline

#2 2012-03-08 01:03:44

cfr
Member
From: Cymru
Registered: 2011-11-27
Posts: 7,131

Re: Runlevels on GRUB2

Do you want to handle grub2's config file manually or automatically (using the grub-mkconfig etc.)?

I adapted a file to get automatically generated entries when grub-mkconfig is run. I just discovered it probably needs updating but I can post that when I've looked at it a bit if you want an example. (It is based on /etc/grub.d/10_linux which has been updated, I think, so I need to update my mangled version to follow suit.) I did this to get entries for booting into run level 3.

Whichever method you use, your changes won't get overwritten on kernel update. If updates are needed, you will need to see to that.

Last edited by cfr (2012-03-08 01:05:33)


CLI Paste | How To Ask Questions

Arch Linux | x86_64 | GPT | EFI boot | refind | stub loader | systemd | LVM2 on LUKS
Lenovo x270 | Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz | Intel Wireless 8265/8275 | US keyboard w/ Euro | 512G NVMe INTEL SSDPEKKF512G7L

Offline

#3 2012-03-08 01:17:47

OakRaider4Life
Member
Registered: 2012-02-08
Posts: 98

Re: Runlevels on GRUB2

I would much prefer to handle the config file automatically, as the automatic handling is the main reason I moved to GRUB2.

A file lik that though sounds like exactly what I could use smile please do post it when you get a chance.

Offline

#4 2012-03-08 02:43:48

cfr
Member
From: Cymru
Registered: 2011-11-27
Posts: 7,131

Re: Runlevels on GRUB2

OK. Note that I haven't tested this but you can run diff against 10_linux to see how similiar it is to the default:

 
#! /bin/sh
set -e

# grub-mkconfig helper script.
# Copyright (C) 2006,2007,2008,2009,2010  Free Software Foundation, Inc.
#
# GRUB is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GRUB is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GRUB.  If not, see <http://www.gnu.org/licenses/>.

# cfr: mangled to try to produce entries in multi-user mode without X11

prefix=/usr
exec_prefix=${prefix}
bindir=/usr/bin
libdir=${exec_prefix}/lib
datarootdir=/usr/share
. ${libdir}/grub/grub-mkconfig_lib

export TEXTDOMAIN=grub
export TEXTDOMAINDIR=${datarootdir}/locale

CLASS="--class gnu-linux --class gnu --class os"

if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
  OS=GNU/Linux
else
  OS="${GRUB_DISTRIBUTOR}"
  CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | tr -d ' ') ${CLASS}"
fi

# loop-AES arranges things so that /dev/loop/X can be our root device, but
# the initrds that Linux uses don't like that.
case ${GRUB_DEVICE} in
  /dev/loop/*|/dev/loop[0-9])
    GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
  ;;
esac

if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
    || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
    || uses_abstraction "${GRUB_DEVICE}" lvm; then
  LINUX_ROOT_DEVICE=${GRUB_DEVICE}
else
  LINUX_ROOT_DEVICE="/dev/disk/by-uuid/${GRUB_DEVICE_UUID}"
fi

if [ "x`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`" = xbtrfs ]; then
  rootsubvol="`make_system_path_relative_to_its_root /`"
  rootsubvol="${rootsubvol#/}"
  if [ "x${rootsubvol}" != x ]; then
    GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
  fi
fi

linux_entry ()
{
  os="$1"
  version="$2"
  recovery="$3"
  args="$4"
  if [ -n "$5" ] ; then
    title="$(gettext_quoted "%s, with Linux %s (no X11)") $5"
  elif ${recovery} ; then
    title="$(gettext_quoted "%s, with Linux %s (recovery mode)")"
  else
    title="$(gettext_quoted "%s, with Linux %s (no X11)")"
  fi
  printf "menuentry '${title}' ${CLASS} {\n" "${os}" "${version}"
  if ! ${recovery} ; then
      save_default_entry | sed -e "s/^/\t/"
  fi

  # 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 ]; then
      cat << EOF
        load_video
EOF
      if grep -qx "CONFIG_FB_EFI=y" "${config}" 2> /dev/null \
          && grep -qx "CONFIG_VT_HW_CONSOLE_BINDING=y" "${config}" 2> /dev/null; then
          cat << EOF
        set gfxpayload=keep
EOF
      fi
  else
      if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
          cat << EOF
        load_video
EOF
      fi
          cat << EOF
        set gfxpayload=$GRUB_GFXPAYLOAD_LINUX
EOF
  fi

  cat << EOF
        insmod gzio
EOF

  if [ x$dirname = x/ ]; then
    if [ -z "${prepare_root_cache}" ]; then
      prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/")"
    fi
    printf '%s\n' "${prepare_root_cache}"
  else
    if [ -z "${prepare_boot_cache}" ]; then
      prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")"
    fi
    printf '%s\n' "${prepare_boot_cache}"
  fi

  message="$(gettext_printf "Loading Linux %s ..." ${version})"

  cat << EOF
        echo    '$message'
        linux   ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro 3 ${args}
EOF
  if test -n "${initrd}" ; then
    message="$(gettext_printf "Loading initial ramdisk ...")"
    cat << EOF
        echo    '$message'
        initrd  ${rel_dirname}/${initrd}
EOF
  fi
  cat << EOF
}
EOF
}

case x`uname -m` in
    xi?86 | xx86_64)
        list=`for i in /boot/vmlinuz-* /vmlinuz-* /boot/kernel-* /boot/vmlinuz26-* ; do
                  if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
              done` ;;
    *) 
        list=`for i in /boot/vmlinuz* /boot/vmlinux* /vmlinuz* /vmlinux* /boot/kernel-* ; do
                  if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
             done` ;;
esac

prepare_boot_cache=
prepare_root_cache=

while [ "x$list" != "x" ] ; do
  linux=`version_find_latest $list`
  echo "Found linux image: $linux" >&2
  basename=`basename $linux`
  dirname=`dirname $linux`
  rel_dirname=`make_system_path_relative_to_its_root $dirname`
  version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
  base_init=`echo $basename | sed -e "s,vmlinuz,initramfs,g"`
  alt_version="${base_init}-fallback"
  linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"

  initrd=

  for i in "initrd.img-${version}" "initrd-${version}.img" "initrd-${version}.gz" \
           "initrd-${version}" "initramfs-${version}.img" \
           "initrd.img-${alt_version}" "initrd-${alt_version}.img" \
           "initrd-${alt_version}" "initramfs-${alt_version}.img" \
           "initramfs-genkernel-${version}" \
           "initramfs-genkernel-${alt_version}" \
           "${basename/vmlinuz/initramfs}.img" "${basename/vmlinuz/kernel}.img"; do
    if test -e "${dirname}/${i}" ; then
      initrd="$i"
      break
    fi
  done

  config=
  for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
    if test -e "${i}" ; then
      config="${i}"
      break
    fi
  done

  initramfs=
  if test -n "${config}" ; then
      initramfs=`grep CONFIG_INITRAMFS_SOURCE= "${config}" | cut -f2 -d= | tr -d \"`
  fi

  if test -n "${initrd}" ; then
    echo "Found initrd image: ${dirname}/${initrd}" >&2
  elif test -z "${initramfs}" ; then
    # "UUID=" magic is parsed by initrd or initramfs.  Since there's
    # no initrd or builtin initramfs, it can't work here.
    linux_root_device_thisversion=${GRUB_DEVICE}
  fi

  linux_entry "${OS}" "${version}" false \
      "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
  for i in "initramfs-${version}-fallback.img" \
           "${basename/vmlinuz/initramfs}-fallback.img" "${basename/vmlinuz/kernel}-fallback.img"; do
    if test -e "${dirname}/${i}"; then
      initrd="$i"
      linux_entry "${OS}" "${version}" true \
          "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" Fallback
      break
    fi
  done

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

Basically, for any entry you get for linux in the menu, you should get one with "(no X11)" at the end which should boot you into run level 3 without needing to alter the grub command line.

Last edited by cfr (2012-03-08 02:45:14)


CLI Paste | How To Ask Questions

Arch Linux | x86_64 | GPT | EFI boot | refind | stub loader | systemd | LVM2 on LUKS
Lenovo x270 | Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz | Intel Wireless 8265/8275 | US keyboard w/ Euro | 512G NVMe INTEL SSDPEKKF512G7L

Offline

Board footer

Powered by FluxBB