* Proposed PATCH to allow control of the kernel ordering in grub.cfg
@ 2018-12-19 6:50 Jeff Norden
2018-12-20 11:53 ` Daniel Kiper
2018-12-21 0:26 ` Jeff Norden
0 siblings, 2 replies; 6+ messages in thread
From: Jeff Norden @ 2018-12-19 6:50 UTC (permalink / raw)
To: grub-devel
Greetings.
The small patch below adds a new variable (for use by 10_linux) that
allows you to tweak the ordering of kernels in grub.cfg
When the 10_linux script finds more than one installed kernel, it orders
them by version number. If you have several kernels, the one with the
highest version might be one you are trying out, but not the one that
you want to use most of the time.
The patch below adds a new /etc/default/grub variable for use by 10_linux.
The line
GRUB_PREFERRED_KERNEL="4.14"
will cause the 4.14 kernel to be listed before any others. In particular,
4.14 will be the kernel used for the top-level "simple" menu entry. If
GRUB_PREFERRED_KERNEL is not set, then the behavior of 10_linux isn't changed.
Background: I've been trying out manjaro lately, which has a nice gui
for installing multiple kernels. I discovered that 4.19 wasn't
interacting well with my video card. I got tired of having to
drill-down to the 4.14 kernel entry on each re-boot. But I wanted to
keep 4.19 installed so that I could try it out after updates (and maybe
try to isolate the problem in my "spare" time).
I could have used the GRUB_DEFAULT variable, but that would mean
disabling GRUB_SAVEDEFAULT, and another member of my household uses the
windows partition on this computer :-(. Also, GRUB_DEFAULT would need
to be adjusted if/when other kernels are added/deleted.
I've been using the attached patch for a month or so with no problems
(the kernel has been updated and grub.cfg has been re-build several
times). Right now, I've have the GRUB_PREFERRED_KERNEL="4.14" line
commented out (the video problem is fixed - not by me), and the modified
10_linux works fine in this mode as well.
Thanks,
-Jeff Norden
==== cut here ====x snip x=====
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 4532266be..f2dea11e9 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -193,7 +193,14 @@ submenu_indentation=""
is_top_level=true
while [ "x$list" != "x" ] ; do
- linux=`version_find_latest $list`
+ linux=""
+ if [ "x${GRUB_PREFERRED_KERNEL}" != "x" ]; then
+ linux=`echo $list | tr ' ' '\n' | grep "${GRUB_PREFERRED_KERNEL}" | tr '\n' ' '`
+ fi
+ if [ "x$linux" = "x" ]; then
+ linux=$list
+ fi
+ linux=`version_find_latest $linux`
gettext_printf "Found linux image: %s\n" "$linux" >&2
basename=`basename $linux`
dirname=`dirname $linux`
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 33332360e..8d6aecf22 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -238,7 +238,8 @@ export GRUB_DEFAULT \
GRUB_ENABLE_CRYPTODISK \
GRUB_BADRAM \
GRUB_OS_PROBER_SKIP_LIST \
- GRUB_DISABLE_SUBMENU
+ GRUB_DISABLE_SUBMENU \
+ GRUB_PREFERRED_KERNEL
if test "x${grub_cfg}" != "x"; then
rm -f "${grub_cfg}.new"
diff --git a/docs/grub.texi b/docs/grub.texi
index ecaba9d5c..ac07a453f 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -1502,6 +1502,24 @@ and @samp{default} (@pxref{default}) environment variables as well as saved
default entry using @command{grub-set-default} and value used with
@command{grub-reboot}.
+@item GRUB_PREFERRED_KERNEL
+If this option is set, @command{grub-mkconfig} will list kernels that
+match its value before others. In particular, the ``top-level'' menu
+entry (assuming submenus are enabled) will be the one with the highest
+version number that matches @samp{GRUB_PREFERRED_KERNEL}. For
+example, @verb{|GRUB_PREFERRED_KERNEL="4.14"|} will put the 4.14 kernel
+first in @file{grub.cfg}, even if newer kernel(s) are found.
+
+Matching is done via @command{grep} against the file name of the
+kernel, so regular expressions can be used. For example:
+@verb{|GRUB_PREFERRED_KERNEL='4\.1[0-6]'|} will put any kernels matching
+4.10 thru 4.16 first, starting with the highest version number. Or,
+@verb{|GRUB_PREFERRED_KERNEL='vmlinuz-3\.16-x86_64'|} would match a
+specific kernel file. Note that the simple example in the previous
+paragraph can be written more carefully as
+@verb{|GRUB_PREFERRED_KERNEL='4\.14'|} to force the @samp{.} to match
+a period instead of an arbitrary character.
+
@item GRUB_ENABLE_CRYPTODISK
If set to @samp{y}, @command{grub-mkconfig} and @command{grub-install} will
check for encrypted disks and generate additional commands needed to access
=====x snip x====x snip x====
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: Proposed PATCH to allow control of the kernel ordering in grub.cfg
2018-12-19 6:50 Proposed PATCH to allow control of the kernel ordering in grub.cfg Jeff Norden
@ 2018-12-20 11:53 ` Daniel Kiper
2018-12-21 5:20 ` Mihai Moldovan
2018-12-21 0:26 ` Jeff Norden
1 sibling, 1 reply; 6+ messages in thread
From: Daniel Kiper @ 2018-12-20 11:53 UTC (permalink / raw)
To: Jeff Norden; +Cc: grub-devel
Hi Jeff,
On Wed, Dec 19, 2018 at 12:50:21AM -0600, Jeff Norden wrote:
> Greetings.
>
> The small patch below adds a new variable (for use by 10_linux) that
> allows you to tweak the ordering of kernels in grub.cfg
>
> When the 10_linux script finds more than one installed kernel, it orders
> them by version number. If you have several kernels, the one with the
> highest version might be one you are trying out, but not the one that
> you want to use most of the time.
>
> The patch below adds a new /etc/default/grub variable for use by 10_linux.
> The line
> GRUB_PREFERRED_KERNEL="4.14"
> will cause the 4.14 kernel to be listed before any others. In particular,
> 4.14 will be the kernel used for the top-level "simple" menu entry. If
> GRUB_PREFERRED_KERNEL is not set, then the behavior of 10_linux isn't changed.
>
> Background: I've been trying out manjaro lately, which has a nice gui
> for installing multiple kernels. I discovered that 4.19 wasn't
> interacting well with my video card. I got tired of having to
> drill-down to the 4.14 kernel entry on each re-boot. But I wanted to
> keep 4.19 installed so that I could try it out after updates (and maybe
> try to isolate the problem in my "spare" time).
>
> I could have used the GRUB_DEFAULT variable, but that would mean
> disabling GRUB_SAVEDEFAULT, and another member of my household uses the
> windows partition on this computer :-(. Also, GRUB_DEFAULT would need
> to be adjusted if/when other kernels are added/deleted.
>
> I've been using the attached patch for a month or so with no problems
> (the kernel has been updated and grub.cfg has been re-build several
> times). Right now, I've have the GRUB_PREFERRED_KERNEL="4.14" line
> commented out (the video problem is fixed - not by me), and the modified
> 10_linux works fine in this mode as well.
This looks like nice commit message. So, please rebase your patch on
latest GRUB2 master branch and repost it using "git format-patch" and
"git send-email". And please do not forget to add your Signed-off-by.
You can check how the commit message should look like using "git log"
in the GRUB2 master branch.
And some minor comments below...
> Thanks,
> -Jeff Norden
>
> ==== cut here ====x snip x=====
>
> diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
> index 4532266be..f2dea11e9 100644
> --- a/util/grub.d/10_linux.in
> +++ b/util/grub.d/10_linux.in
> @@ -193,7 +193,14 @@ submenu_indentation=""
>
> is_top_level=true
> while [ "x$list" != "x" ] ; do
> - linux=`version_find_latest $list`
> + linux=""
> + if [ "x${GRUB_PREFERRED_KERNEL}" != "x" ]; then
> + linux=`echo $list | tr ' ' '\n' | grep "${GRUB_PREFERRED_KERNEL}" | tr '\n' ' '`
s/grep/egrep/? And you do not need tr after grep.
> + fi
> + if [ "x$linux" = "x" ]; then
> + linux=$list
> + fi
> + linux=`version_find_latest $linux`
> gettext_printf "Found linux image: %s\n" "$linux" >&2
> basename=`basename $linux`
> dirname=`dirname $linux`
>
> diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
> index 33332360e..8d6aecf22 100644
> --- a/util/grub-mkconfig.in
> +++ b/util/grub-mkconfig.in
> @@ -238,7 +238,8 @@ export GRUB_DEFAULT \
> GRUB_ENABLE_CRYPTODISK \
> GRUB_BADRAM \
> GRUB_OS_PROBER_SKIP_LIST \
> - GRUB_DISABLE_SUBMENU
> + GRUB_DISABLE_SUBMENU \
> + GRUB_PREFERRED_KERNEL
>
> if test "x${grub_cfg}" != "x"; then
> rm -f "${grub_cfg}.new"
>
> diff --git a/docs/grub.texi b/docs/grub.texi
> index ecaba9d5c..ac07a453f 100644
> --- a/docs/grub.texi
> +++ b/docs/grub.texi
> @@ -1502,6 +1502,24 @@ and @samp{default} (@pxref{default}) environment variables as well as saved
> default entry using @command{grub-set-default} and value used with
> @command{grub-reboot}.
>
> +@item GRUB_PREFERRED_KERNEL
> +If this option is set, @command{grub-mkconfig} will list kernels that
> +match its value before others. In particular, the ``top-level'' menu
> +entry (assuming submenus are enabled) will be the one with the highest
> +version number that matches @samp{GRUB_PREFERRED_KERNEL}. For
> +example, @verb{|GRUB_PREFERRED_KERNEL="4.14"|} will put the 4.14 kernel
> +first in @file{grub.cfg}, even if newer kernel(s) are found.
> +
> +Matching is done via @command{grep} against the file name of the
s/grep/egrep/
Daniel
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: Proposed PATCH to allow control of the kernel ordering in grub.cfg
2018-12-20 11:53 ` Daniel Kiper
@ 2018-12-21 5:20 ` Mihai Moldovan
0 siblings, 0 replies; 6+ messages in thread
From: Mihai Moldovan @ 2018-12-21 5:20 UTC (permalink / raw)
To: The development of GNU GRUB, Daniel Kiper, Jeff Norden
[-- Attachment #1.1: Type: text/plain, Size: 1162 bytes --]
* On 12/20/18 12:53 PM, Daniel Kiper wrote:
>> diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
>> index 4532266be..f2dea11e9 100644
>> --- a/util/grub.d/10_linux.in
>> +++ b/util/grub.d/10_linux.in
>> @@ -193,7 +193,14 @@ submenu_indentation=""
>>
>> is_top_level=true
>> while [ "x$list" != "x" ] ; do
>> - linux=`version_find_latest $list`
>> + linux=""
>> + if [ "x${GRUB_PREFERRED_KERNEL}" != "x" ]; then
>> + linux=`echo $list | tr ' ' '\n' | grep "${GRUB_PREFERRED_KERNEL}" | tr '\n' ' '`
>
> s/grep/egrep/?
Just a tiny nit: egrep/fgrep have been deprecated in POSIX/SUS.
Initially, egrep, fgrep and grep were different programs (the rationale for that
being that the original implementers didn't find a way to come up with a
[space/time] efficient generic algorithm usable for all three variants), but
subsequent grep standard specifications were written with the same functionality
exposed via the -E and -F flags.
Unless you really want to target ancient platforms, I'd try to go for grep -E/-F
instead, even if typically egrep/fgrep will stay around as symlinks for quite a
long time.
Mihai
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 898 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Proposed PATCH to allow control of the kernel ordering in grub.cfg
2018-12-19 6:50 Proposed PATCH to allow control of the kernel ordering in grub.cfg Jeff Norden
2018-12-20 11:53 ` Daniel Kiper
@ 2018-12-21 0:26 ` Jeff Norden
2018-12-27 14:23 ` Jeff Norden
1 sibling, 1 reply; 6+ messages in thread
From: Jeff Norden @ 2018-12-21 0:26 UTC (permalink / raw)
To: grub-devel
Hi Daniel,
Thanks for the quick reply! I've made the suggested changes and attached
a "git format-patch" patch below. Hopefully this is what you need. I'm
not much of a git-expert.
Thanks again. Have a great Holiday Season!
-Jeff
On Thu, 20 Dec 2018, Daniel Kiper wrote:
> This looks like nice commit message. So, please rebase your patch on
> latest GRUB2 master branch and repost it using "git format-patch" and
> "git send-email". And please do not forget to add your Signed-off-by.
>
> And some minor comments below...
Signed-off-by: Jeffrey Norden <jeff@math.tntech.edu>
---
docs/grub.texi | 18 ++++++++++++++++++
util/grub-mkconfig.in | 3 ++-
util/grub.d/10_linux.in | 9 ++++++++-
3 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index ecaba9d5c..4aaa151f8 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -1502,6 +1502,24 @@ and @samp{default} (@pxref{default}) environment variables as well as saved
default entry using @command{grub-set-default} and value used with
@command{grub-reboot}.
+@item GRUB_PREFERRED_KERNEL
+If this option is set, @command{grub-mkconfig} will list kernels that
+match its value before others. In particular, the ``top-level'' menu
+entry (assuming submenus are enabled) will be the one with the highest
+version number that matches @samp{GRUB_PREFERRED_KERNEL}. For
+example, @verb{|GRUB_PREFERRED_KERNEL="4.14"|} will put the 4.14 kernel
+first in @file{grub.cfg}, even if newer kernel(s) are found.
+
+Matching is done via @command{egrep} against the file name of the
+kernel, so regular expressions can be used. For example:
+@verb{|GRUB_PREFERRED_KERNEL='4\.1[0-6]'|} will put any kernels matching
+4.10 thru 4.16 first, starting with the highest version number. Or,
+@verb{|GRUB_PREFERRED_KERNEL='vmlinuz-3\.16-x86_64'|} would match a
+specific kernel file. Note that the simple example in the previous
+paragraph can be written more carefully as
+@verb{|GRUB_PREFERRED_KERNEL='4\.14'|} to force the @samp{.} to match
+a period instead of an arbitrary character.
+
@item GRUB_ENABLE_CRYPTODISK
If set to @samp{y}, @command{grub-mkconfig} and @command{grub-install} will
check for encrypted disks and generate additional commands needed to access
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 33332360e..8d6aecf22 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -238,7 +238,8 @@ export GRUB_DEFAULT \
GRUB_ENABLE_CRYPTODISK \
GRUB_BADRAM \
GRUB_OS_PROBER_SKIP_LIST \
- GRUB_DISABLE_SUBMENU
+ GRUB_DISABLE_SUBMENU \
+ GRUB_PREFERRED_KERNEL
if test "x${grub_cfg}" != "x"; then
rm -f "${grub_cfg}.new"
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 4532266be..32affd9d6 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -193,7 +193,14 @@ submenu_indentation=""
is_top_level=true
while [ "x$list" != "x" ] ; do
- linux=`version_find_latest $list`
+ linux=""
+ if [ "x${GRUB_PREFERRED_KERNEL}" != "x" ]; then
+ linux=`echo $list | tr ' ' '\n' | egrep "${GRUB_PREFERRED_KERNEL}"`
+ fi
+ if [ "x$linux" = "x" ]; then
+ linux=$list
+ fi
+ linux=`version_find_latest $linux`
gettext_printf "Found linux image: %s\n" "$linux" >&2
basename=`basename $linux`
dirname=`dirname $linux`
--
2.19.2
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: Proposed PATCH to allow control of the kernel ordering in grub.cfg
2018-12-21 0:26 ` Jeff Norden
@ 2018-12-27 14:23 ` Jeff Norden
2018-12-31 8:09 ` Mihai Moldovan
0 siblings, 1 reply; 6+ messages in thread
From: Jeff Norden @ 2018-12-27 14:23 UTC (permalink / raw)
To: grub-devel
Well, DRAT!
Nothing is ever as simple as it seems, is it?
1) Deleting the tr after the grep actually seems to break the patch. My
apologies for not testing this more carefully in advance. It looks like
the second tr masks grep's exit status, which is important b/c the
script runs with 'set -e' and exits immediately on any "error". Seems
like changing |tr to ||true will work.
2) After reading Mihai Moldovan's comments above, I think it is better
to just use grep rather than egrep. You could always add "-E" at the
beginning of the GRUB_PREFERRED_KERNEL string if you need to. With GNU
grep, egrep and grep have the same functionality, and only differ in
when you need to backslash-escape some of the special characters.
3) Thinking about the second point, people might want to include other
grep flags in GRUB_PREFERRED_KERNEL, such as "-F", "-i", "-x", or even
"-P" (my personal favorite :-). BUT, it then becomes clear that you
can't count 100% on grep to either return an empty string or entries
from $list. If you accidentally include "-l" or "-c", then $linux might
be set to "(standard input)" or "1". Potentially, this could put
10_linux into an infinite loop, but it would probably just crash quickly
due to "set -e" again. In any case, this could leave someone's system
in an un-bootable state. So, I think it will be necessary to check the
result of `grep "${GRUB_PREFERRED_KERNEL}"` more carefully.
Hopefully, I'll have some time to work on this next week. I'll submit a
revised patch when I get it fixed. I'm afraid it won't be quite as
simple as I originally thought, but it shouldn't be too much longer.
Happy New Year's to all!
-Jeff
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: Proposed PATCH to allow control of the kernel ordering in grub.cfg
2018-12-27 14:23 ` Jeff Norden
@ 2018-12-31 8:09 ` Mihai Moldovan
0 siblings, 0 replies; 6+ messages in thread
From: Mihai Moldovan @ 2018-12-31 8:09 UTC (permalink / raw)
To: The development of GNU GRUB, Jeff Norden
[-- Attachment #1.1: Type: text/plain, Size: 4823 bytes --]
* On 12/27/18 3:23 PM, Jeff Norden wrote:
> Nothing is ever as simple as it seems, is it?
Never is.
> 1) Deleting the tr after the grep actually seems to break the patch. My
> apologies for not testing this more carefully in advance. It looks like
> the second tr masks grep's exit status, which is important b/c the
> script runs with 'set -e' and exits immediately on any "error".
Careful, that's not universally true. Some shells error out, others don't.
POSIX/SUS (at least in its current iteration) specifies that "any command" with
a few exceptions (a few reserved words, any but the last command in pipes, any
but the last command in an AND-OR list and some other exception I wasn't able to
understand even after thinking about it for half an hour) shall make the shell
fail. However, bash for instance didn't care for stuff that happens in subshells
(which backticks or the better $() notation create) before version 4, so it
seems that older versions would NOT error out if anything within a subshell
failed. Newer ones do, but there are even more caveats.
Consider
[1] (set -e; printf '%s\n' 'blargh' | grep -E 'foo'; printf '%s\n' 'bar');
printf '%s\n' "${?}"
which should print "1\n", but
[2] (set -e; ret="$(printf '%s\n' 'blargh' | grep -E 'foo'; printf '%s\n'
'bar')"; printf '%s\n' "${ret}"); printf '%s\n' "${?}"
which prints "bar\n0\n" in my bash version and then again
[3] (set -e; ret="$(set -e; printf '%s\n' 'blargh' | grep -E 'foo'; printf
'%s\n' 'bar')"; printf '%s\n' "${ret}"); printf '%s\n' "${?}"
which prints "1\n" again.
In older bash versions, any error within the subshell would have been ignored
(contrary to POSIX requirements), so in my understanding [2] and [3] would have
printed the same "bar\n0\n" string there.
The errexit shell feature can be and often is a venomous snake pit.
> Seems like changing |tr to ||true will work.
Yeah, the usual workaround for that is either "cmdthatmightfail || true" or
"cmdthatmightfail || :"
> 2) After reading Mihai Moldovan's comments above, I think it is better
> to just use grep rather than egrep. You could always add "-E" at the
> beginning of the GRUB_PREFERRED_KERNEL string if you need to. With GNU
> grep, egrep and grep have the same functionality, and only differ in
> when you need to backslash-escape some of the special characters.
No, don't even start with that. Either use
egrep "${GRUB_PREFERRED_KERNEL}"
or
grep -E "${GRUB_PREFERRED_KERNEL}"
Why?
ionic@apgunner ~/ $ input="-E 4.20"; grep "${input}" '/dev/null'
grep: invalid option -- ' '
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
In such a scenario, because the input string is quoted, it will be passed as one
single argument to the grep utility, which then tries to parse the full string
as one huge option. Take into consideration that short options can be usually
concatenated together, so grep's option parsing tries to adhere to this as soon
as it saw the short option starting sequence "-". Funnily enough, a short option
such as "- " might just be valid. It just turns out that grep doesn't support it.
A remedy to this could be to prefix any user-provided input with the
options-terminating pseudo-option "--" (often called delimiter).
input="-E 4.20"; grep -- "${input}" /dev/null
would work "correctly" (if you really *intended* to search for a string such as
"-E 4.20" or "-E 4,20" or "-E 4a20" or ...), but also not treat anything that
might resemble an option in the user string as a real option, which usually is
the right thing to do. Input sanitization or lack thereof is a huge problem. You
generally do not want users to pass random options to commands, for the reasons
you have outlined yourself in point 3.
The problem is just that command line parsing is difficult and while "--" is an
accepted delimiter for getopt() and friends, there are utilities that don't even
use getopt(), but instead roll their custom solution that happens to not support
that. Another common exception to this is bash's "echo" builtin which explicitly
does not handle "--" as a delimiter. Also, people are lazy and don't like to
clutter every command invocation with a delimiter after specifying wanted
options and even when they actually try to, it's oh-so-easy to forget.
To my mind, grep -E -- "${GRUB_PREFERRED_KERNEL}" sounds like the best solution.
You obviously already took into account that dots in regular expressions match
arbitrary characters and outlined that, including consequences, in the
documentation; good work on that!
Originally, I was just trying to point out that I'd prefer to use "grep -E"
nowadays compared to "egrep" - seems like we went off the rail pretty quickly. :)
Mihai
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 898 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2018-12-31 8:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-12-19 6:50 Proposed PATCH to allow control of the kernel ordering in grub.cfg Jeff Norden
2018-12-20 11:53 ` Daniel Kiper
2018-12-21 5:20 ` Mihai Moldovan
2018-12-21 0:26 ` Jeff Norden
2018-12-27 14:23 ` Jeff Norden
2018-12-31 8:09 ` Mihai Moldovan
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.