Announcement

Collapse
No announcement yet.

Add GRUB entry for extra option to boot in text mode?

Collapse
This topic is closed.
X
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    #16
    Originally posted by oshunluvr View Post
    However, to have a text only and a graphical boot option is a bit more complex. You'd have to have a custom stanza in grub or something like that. That would be difficult to manage IMO -too much manual work required. Theoretically, you could write a script that would automagically create a custom boot stanza from your grub.cfg and have it execute when you ran "update-grub" - that would work but it will take some creative thinking and good bash scripting
    BTW, if I understood you correctly, this video I linked earlier shows how to do that.

    https://www.youtube.com/watch?v=TDf_fRAophc

    All it takes is to edit the file

    Code:
    /etc/grub.d/40_custom
    Add the custom stanza there...

    Code:
    menuentry '[B][COLOR=#ff0000]Ubuntu (HEADLESS)[/COLOR][/B]' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' {        recordfail
          load_video
          gfxmode $linux_gfx_mode
          insmod gzio
          if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
          insmod part_gpt
          insmod ext2
          set root='hd0,gpt2'
          if [ x$feature_platform_search_hint = xy ]; then
            search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          else
            search --no-floppy --fs-uuid --set=root xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          fi
          linux /boot/vmlinuz-4.10.0-22-generic.efi.signed root=UUID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ro [B][COLOR=#ff0000]text systemd.unit=multi-user.target[/COLOR][/B] $vt_handoff
          initrd  /boot/initrd.img-4.10.0-22-generic
    }
    ..and run update-grub

    Comment


      #17
      Oh my! Just as I posted that I noticed that the $vt_handoff param wasn't there in the grub.conf when I changed it from "quiet splash" to "text" as you suggested.
      I tried editing the custom stanza, deleting the $vt_handoff param and now it works.. still will never use it but what the hell! hahaha

      Comment


        #18
        Here's what I thought up: Like I said, a script could build a custom grub entry for you. These commands, executed via a script from within update-grub would build a custom entry and put it in grub.cfg:

        Code:
        sed '144,160!d' /boot/grub/grub.cfg >> /root/customgrub.txt
        sed -i 's/quiet splash/text/' /root/customgrub.txt 
        cat /root/customgrub.txt >> /boot/grub/grub.cfg
        The logic is:
        Line 1 copies the first menuentry from grub.cfg and makes a file with it in root home. The numbers 144 and 160 are the line numbers in grub.cfg of the first menu entry.
        Line 2 replaces "quiet splash" with "text". You could use "systemd.unit=multi-user.target" instead if that works better.
        Line 3 puts the new stanza at the end of grub.cfg

        This is just a first shot off the top of my head. There are a couple bash experts on here that will tear this apart - but it's a fun idea.

        The first potential problem I see is if the grub.cfg changed the number of lines, this would fail because the custom entry would be truncated or too long, etc. The second is if you edited /usr/sbin/update-grub to add the script or the above commands, it might get wiped out by a future update. I'm sure there are other potential issues, I haven't thought of.

        One good thing is since it adds at the bottom of grub.cfg, it's unlikely it would leave you win an unbootable condition.

        Anyway- it would be a fun experiment.

        Please Read Me

        Comment


          #19
          All it takes is to edit the file

          Code:
          /etc/grub.d/40_custom

          Add the custom stanza there...

          Code:
          menuentry 'Ubuntu (HEADLESS)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' { recordfail
          load_video
          gfxmode $linux_gfx_mode
          insmod gzio
          if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
          insmod part_gpt
          insmod ext2
          set root='hd0,gpt2'
          if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          else
          search --no-floppy --fs-uuid --set=root xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          fi
          linux /boot/vmlinuz-4.10.0-22-generic.efi.signed root=UUID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ro text systemd.unit=multi-user.target $vt_handoff
          initrd /boot/initrd.img-4.10.0-22-generic
          }

          ..and run update-grub
          The problem with the above here is every time you install a new kernel, you'd have to redo your custom entry.

          Please Read Me

          Comment


            #20
            Originally posted by oshunluvr View Post
            The problem with the above here is every time you install a new kernel, you'd have to redo your custom entry.
            True that.

            Originally posted by oshunluvr View Post
            Here's what I thought up: Like I said, a script could build a custom grub entry for you. These commands, executed via a script from within update-grub would build a custom entry and put it in grub.cfg:

            Code:
            sed '144,160!d' /boot/grub/grub.cfg >> /root/customgrub.txt
            sed -i 's/quiet splash/text/' /root/customgrub.txt 
            cat /root/customgrub.txt >> /boot/grub/grub.cfg
            The logic is:
            Line 1 copies the first menuentry from grub.cfg and makes a file with it in root home. The numbers 144 and 160 are the line numbers in grub.cfg of the first menu entry.
            Line 2 replaces "quiet splash" with "text". You could use "systemd.unit=multi-user.target" instead if that works better.
            Line 3 puts the new stanza at the end of grub.cfg

            This is just a first shot off the top of my head. There are a couple bash experts on here that will tear this apart - but it's a fun idea.

            The first potential problem I see is if the grub.cfg changed the number of lines, this would fail because the custom entry would be truncated or too long, etc. The second is if you edited /usr/sbin/update-grub to add the script or the above commands, it might get wiped out by a future update. I'm sure there are other potential issues, I haven't thought of.

            One good thing is since it adds at the bottom of grub.cfg, it's unlikely it would leave you win an unbootable condition.

            Anyway- it would be a fun experiment.
            Looks like a job for regular expressions maybe? That would presumably help avoid line number issues.
            Perhaps it could be done by reading from grub.conf, writing to 40_custom, then running update-grub

            it definitely sounds fun!

            Comment


              #21
              Originally posted by dazz.. View Post
              Perhaps it could be done by reading from grub.conf, writing to 40_custom, then running update-grub
              I thought of that but couldn't figure a way to do it without running grub-mkconfig (within update-grub) twice - because if you do the stanza copy before the grub-mkconfig command (see "cat /usr/sbin/update-grub") then it would be one step behind. If you did the stanza copy after grub-mkconfig, it wouldn't be in grub.cfg. Seemed silly to run the command grub-mkconfig twice every time.

              However, you can determine the line numbers:

              Code:
              grep -n -m 1 "menuentry 'GNU/Linux" /boot/grub/grub.cfg |cut -c 1-3
              expr `grep -n -m 1 "initrd" /boot/grub/grub.cfg | cut -c 1-3 ` + 1
              First line gets the beginning line of the first menuentry stanza and second gets the end line number.

              Please Read Me

              Comment


                #22
                This seems to work:
                Code:
                BEGIN=$(grep -n -m 1 "menuentry 'GNU/Linux" /boot/grub/grub.cfg |cut -c 1-3 )
                END=$(expr `grep -n -m 1 "initrd" /boot/grub/grub.cfg | cut -c 1-3 ` + 1 )
                sed -n $BEGIN,${END}p /boot/grub/grub.cfg >> /root/customgrub.txt
                sed -i 's/quiet splash/text/' /root/customgrub.txt 
                cat /root/customgrub.txt >> /boot/grub/grub.cfg

                Please Read Me

                Comment


                  #23
                  Of course, the above "cut" commands assumes line numbers of only three digits. Still a potential trap but a smaller one.
                  Last edited by oshunluvr; Jun 17, 2017, 10:06 AM.

                  Please Read Me

                  Comment


                    #24
                    Thanks oshunluvr. This is not something I can just copy-paste. I need to have a good handle on what the script does and how, in case I need to troubleshoot it some day.
                    Something just ocurred to me. What generates the grub.conf every time update-grub runs? Is it some of the scripts at /etc/grub.d? Can those be edited to generate the extra entry?

                    Comment


                      #25
                      There's no magic in that script - just some basic bash stuff. There's plenty of web sources to explain each piece. Besides, if it stopped working some time in the future you wouldn't be any worse off than you are right now.

                      Here's the contents of update-grub:
                      Code:
                      [FONT=monospace]#!/bin/sh
                      set -e
                      exec grub-mkconfig -o /boot/grub/grub.cfg "$@"
                      [/FONT]
                      So you see it's just a bash script that calls "grub-mkconfig"

                      Here's the contents of grub-mkconfig:
                      Code:
                      [FONT=monospace][COLOR=#000000]#! /bin/sh[/COLOR]
                      set -e
                      
                      # Generate grub.cfg by inspecting /boot contents.
                      # 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/>.
                      
                      prefix="/usr"
                      exec_prefix="/usr"
                      datarootdir="/usr/share"
                      
                      prefix="/usr"
                      exec_prefix="/usr"
                      sbindir="${exec_prefix}/sbin"
                      bindir="${exec_prefix}/bin"
                      sysconfdir="/etc"
                      PACKAGE_NAME=GRUB
                      PACKAGE_VERSION=2.02~beta2-36ubuntu3.11
                      host_os=linux-gnu
                      datadir="${datarootdir}"
                      if [ "x$pkgdatadir" = x ]; then
                          pkgdatadir="${datadir}/grub"
                      fi
                      grub_cfg=""
                      grub_mkconfig_dir="${sysconfdir}"/grub.d
                      
                      self=`basename $0`
                      
                      grub_probe="${sbindir}/grub-probe"
                      grub_file="${bindir}/grub-file"
                      grub_editenv="${bindir}/grub-editenv"
                      grub_script_check="${bindir}/grub-script-check"
                      
                      export TEXTDOMAIN=grub
                      export TEXTDOMAINDIR="${datarootdir}/locale"
                      
                      . "${pkgdatadir}/grub-mkconfig_lib"
                      
                      # Usage: usage
                      # Print the usage.
                      usage () {
                          gettext_printf "Usage: %s [OPTION]\n" "$self"
                          gettext "Generate a grub config file"; echo
                          echo
                          print_option_help "-o, --output=$(gettext FILE)" "$(gettext "output generated config to FILE [default=stdout]")"
                          print_option_help "-h, --help" "$(gettext "print this message and exit")"
                          print_option_help "-v, --version" "$(gettext "print the version information and exit")"
                          echo
                          gettext "Report bugs to <bug-grub@gnu.org>."; echo
                      }
                      
                      argument () {
                        opt=$1
                        shift
                      
                        if test $# -eq 0; then
                            gettext_printf "%s: option requires an argument -- \`%s'\n" "$self" "$opt" 1>&2
                            exit 1
                        fi
                        echo $1
                      }
                      
                      # Check the arguments.
                      while test $# -gt 0
                      do
                          option=$1
                          shift
                      
                          case "$option" in
                          -h | --help)
                              usage
                              exit 0 ;;
                          -v | --version)
                              echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
                              exit 0 ;;
                          -o | --output)
                              grub_cfg=`argument $option "$@"`; shift;;
                          --output=*)
                              grub_cfg=`echo "$option" | sed 's/--output=//'`
                              ;;
                          -*)
                              gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2
                              usage
                              exit 1
                              ;;
                          # Explicitly ignore non-option arguments, for compatibility.
                          esac
                      done
                      
                      if fgrep -qs '${GRUB_PREFIX}/video.lst' "${grub_mkconfig_dir}/00_header"; then
                        echo "GRUB >= 2.00 has been unpacked but not yet configured." >&2
                        echo "grub-mkconfig will not work until the upgrade is complete." >&2
                        echo "It should run later as part of configuring the new GRUB packages." >&2
                        exit 0
                      fi
                      
                      if [ "x$EUID" = "x" ] ; then
                        EUID=`id -u`
                      fi
                      
                      if [ "$EUID" != 0 ] ; then
                        root=f
                        case "`uname 2>/dev/null`" in
                          CYGWIN*)
                            # Cygwin: Assume root if member of admin group
                            for g in `id -G 2>/dev/null` ; do
                              case $g in
                                0|544) root=t ;;
                              esac
                            done ;;
                        esac
                        if [ $root != t ] ; then
                          gettext_printf "%s: You must run this as root\n" "$self" >&2
                          exit 1
                        fi
                      fi
                      
                      set $grub_probe dummy
                      if test -f "$1"; then
                          :
                      else
                          gettext_printf "%s: Not found.\n" "$1" 1>&2
                          exit 1
                      fi
                      
                      # Device containing our userland.  Typically used for root= parameter.
                      GRUB_DEVICE="`${grub_probe} --target=device /`"
                      GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
                      
                      # Device containing our /boot partition.  Usually the same as GRUB_DEVICE.
                      GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
                      GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true
                      
                      # Filesystem for the device containing our userland.  Used for stuff like
                      # choosing Hurd filesystem module.
                      GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`"
                      
                      if [ x"$GRUB_FS" = xunknown ]; then
                          GRUB_FS="$(stat -f --printf=%T / || echo unknown)"
                      fi
                      
                      if test -f ${sysconfdir}/default/grub ; then
                        . ${sysconfdir}/default/grub
                      fi
                      for x in ${sysconfdir}/default/grub.d/*.cfg ; do
                        if [ -e "${x}" ]; then
                          . "${x}"
                        fi
                      done
                      
                      # XXX: should this be deprecated at some point?
                      if [ "x${GRUB_TERMINAL}" != "x" ] ; then
                        GRUB_TERMINAL_INPUT="${GRUB_TERMINAL}"
                        GRUB_TERMINAL_OUTPUT="${GRUB_TERMINAL}"
                      fi
                      
                      termoutdefault=0
                      if [ "x${GRUB_TERMINAL_OUTPUT}" = "x" ]; then
                          GRUB_TERMINAL_OUTPUT=gfxterm;
                          termoutdefault=1;
                      fi
                      
                      for x in ${GRUB_TERMINAL_OUTPUT}; do
                          case "x${x}" in
                              xgfxterm) ;;
                              xconsole | xserial | xofconsole | xvga_text)
                                  # make sure all our children behave in conformance with ascii..
                                  export LANG=C;;
                              *) echo "Invalid output terminal \"${GRUB_TERMINAL_OUTPUT}\"" >&2 ; exit 1 ;;
                          esac
                      done
                      
                      GRUB_ACTUAL_DEFAULT="$GRUB_DEFAULT"
                      
                      if [ "x${GRUB_ACTUAL_DEFAULT}" = "xsaved" ] ; then GRUB_ACTUAL_DEFAULT="`"${grub_editenv}" - list | sed -n '/^saved_entry=/ s,^saved_entry=,,p'`" ; fi
                      
                      if [ "x${GRUB_RECOVERY_TITLE}" = "x" ]; then
                        GRUB_RECOVERY_TITLE="recovery mode"
                      fi
                      
                      
                      # These are defined in this script, export them here so that user can
                      # override them.
                      export GRUB_DEVICE \
                        GRUB_DEVICE_UUID \
                        GRUB_DEVICE_BOOT \
                        GRUB_DEVICE_BOOT_UUID \
                        GRUB_FS \
                        GRUB_FONT \
                        GRUB_PRELOAD_MODULES \
                        GRUB_ACTUAL_DEFAULT
                      
                      # These are optional, user-defined variables.
                      export GRUB_DEFAULT \
                        GRUB_HIDDEN_TIMEOUT \
                        GRUB_HIDDEN_TIMEOUT_QUIET \
                        GRUB_TIMEOUT \
                        GRUB_TIMEOUT_STYLE \
                        GRUB_DEFAULT_BUTTON \
                        GRUB_HIDDEN_TIMEOUT_BUTTON \
                        GRUB_TIMEOUT_BUTTON \
                        GRUB_TIMEOUT_STYLE_BUTTON \
                        GRUB_BUTTON_CMOS_ADDRESS \
                        GRUB_BUTTON_CMOS_CLEAN \
                        GRUB_DISTRIBUTOR \
                        GRUB_CMDLINE_LINUX \
                        GRUB_CMDLINE_LINUX_DEFAULT \
                        GRUB_CMDLINE_XEN \
                        GRUB_CMDLINE_XEN_DEFAULT \
                        GRUB_CMDLINE_LINUX_XEN_REPLACE \
                        GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT \
                        GRUB_CMDLINE_NETBSD \
                        GRUB_CMDLINE_NETBSD_DEFAULT \
                        GRUB_CMDLINE_GNUMACH \
                        GRUB_TERMINAL_INPUT \
                        GRUB_TERMINAL_OUTPUT \
                        GRUB_SERIAL_COMMAND \
                        GRUB_DISABLE_LINUX_UUID \
                        GRUB_DISABLE_RECOVERY \
                        GRUB_VIDEO_BACKEND \
                        GRUB_GFXMODE \
                        GRUB_BACKGROUND \
                        GRUB_THEME \
                        GRUB_GFXPAYLOAD_LINUX \
                        GRUB_DISABLE_OS_PROBER \
                        GRUB_INIT_TUNE \
                        GRUB_SAVEDEFAULT \
                        GRUB_ENABLE_CRYPTODISK \
                        GRUB_BADRAM \
                        GRUB_OS_PROBER_SKIP_LIST \
                        GRUB_DISABLE_SUBMENU \
                        GRUB_RECORDFAIL_TIMEOUT \
                        GRUB_RECOVERY_TITLE \
                        GRUB_FORCE_PARTUUID \
                        GRUB_DISABLE_INITRD
                      
                      if test "x${grub_cfg}" != "x"; then
                        rm -f "${grub_cfg}.new"
                        oldumask=$(umask); umask 077
                        exec > "${grub_cfg}.new"
                        umask $oldumask
                      fi
                      gettext "Generating grub configuration file ..." >&2
                      echo >&2
                      
                      cat << EOF
                      #
                      # DO NOT EDIT THIS FILE
                      #
                      # It is automatically generated by $self using templates
                      # from ${grub_mkconfig_dir} and settings from ${sysconfdir}/default/grub
                      #
                      EOF
                      
                      
                      for i in "${grub_mkconfig_dir}"/* ; do
                        case "$i" in
                          # emacsen backup files. FIXME: support other editors
                          *~) ;;
                          # emacsen autosave files. FIXME: support other editors
                          */\#*\#) ;;
                          *)
                            if grub_file_is_not_garbage "$i" && test -x "$i" ; then
                              echo
                              echo "### BEGIN $i ###"
                              "$i"
                              echo "### END $i ###"
                            fi
                          ;;
                        esac
                      done
                      
                      if [ "x${grub_cfg}" != "x" ] && ! grep "^password" ${grub_cfg}.new >/dev/null; then
                        chmod 444 ${grub_cfg}.new || true
                      fi
                      
                      if test "x${grub_cfg}" != "x" ; then
                        if ! ${grub_script_check} ${grub_cfg}.new; then
                          # TRANSLATORS: %s is replaced by filename
                          gettext_printf "Syntax errors are detected in generated GRUB config file.
                      Ensure that there are no errors in /etc/default/grub
                      and /etc/grub.d/* files or please file a bug report with
                      %s file attached." "${grub_cfg}.new" >&2
                          echo >&2
                        else
                          # none of the children aborted with error, install the new grub.cfg
                          mv -f ${grub_cfg}.new ${grub_cfg}
                        fi
                      fi
                      
                      gettext "done" >&2
                      echo >&2
                      [/FONT]
                      I suppose you could edit this to get the results you want, but any future upgrade would wipe out your edits. I think it would be smarter to have an independent script that was safe from upgrades. A single line added to update-grub could call it and that would be an easy re-do if update-grub got replaced.
                      Last edited by oshunluvr; Jun 18, 2017, 05:30 AM.

                      Please Read Me

                      Comment


                        #26
                        What oshunluver said:
                        https://www.digitalocean.com/communi...nit-management
                        "A nation that is afraid to let its people judge the truth and falsehood in an open market is a nation that is afraid of its people.”
                        – John F. Kennedy, February 26, 1962.

                        Comment


                          #27
                          Originally posted by oshunluvr
                          The problem with the above here is every time you install a new kernel, you'd have to redo your custom entry.
                          The usual fix for this is to use the vmlinux and initrd.img symbolic links in /.
                          Code:
                          linux /vmlinux root=[I]<blah blah>[/I]
                          initrd /initrd.img
                          (Every time a new kernel is installed, the symbolic links are updated, by APT I guess.)

                          Or am I missing something here?
                          Regards, John Little

                          Comment


                            #28
                            Originally posted by jlittle View Post
                            The usual fix for this is to use the vmlinux and initrd.img symbolic links in /.
                            Code:
                            linux /vmlinux root=[I]<blah blah>[/I]
                            initrd /initrd.img
                            (Every time a new kernel is installed, the symbolic links are updated, by APT I guess.)

                            Or am I missing something here?
                            Nah, that seems too easy. Obviously, I didn't think of that. Not all distros generate the symlinks to the image, but *buntus sure do.

                            Please Read Me

                            Comment


                              #29
                              Googling it as we speak. Thanks for the suggestion

                              Comment


                                #30
                                I had forgotten that, as well. Actually, many of us here KNEW it, though (including oshuluvr) as we often used a separate GRUB partition that contained a GRUB menu that worked by symlinks (so we wouldn't have to continually edit it at every kernel upgrade).
                                An intellectual says a simple thing in a hard way. An artist says a hard thing in a simple way. Charles Bukowski

                                Comment

                                Working...
                                X