Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

CentOS 7 learn used grub entry

With the major changes introduced in CentOS 7 from CentOS 6 (systemd, grub2, and more), determining exactly which grub menu entry will be used at next boot is a little more difficult than before. I wrote a quick script that calculates this for you: learn-used-grub- entry

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/bin/sh
# File: learn-used-grub-entry
# Location: /usr/bin
# Author: bgstack15
# Startdate: 2019-01-28 11:27
# Title: Script that Determines Which Grub Entry Will be Used
# Purpose:
# Package: bgscripts
# History:
# Usage:
#    for RHEL7/grub2
# Reference:
#    original research
# Improve:

test -z "${LUGE_GRUB_CFG}" && LUGE_GRUB_CFG=/boot/grub2/grub.cfg
test -z "${LUGE_ETC_DEFAULT_GRUB}" && LUGE_ETC_DEFAULT_GRUB=/etc/default/grub
# use option LUGE_OUTPUT which is one of ["kernel","","initram"]

grub_saved_name="$( grub2-editenv - list | awk -F'=' '{print $NF}' )"
use_number="$( awk -F'=' '/^GRUB_DEFAULT/{print $NF}' "${LUGE_ETC_DEFAULT_GRUB}" )"

use_entry=""
# calculate true value
if test "$( echo "${use_number}" | tr '[[:upper:]]' '[[:lower:]]' )" = "saved" ;
then
   # it is the saved value (which is same as last used)
   use_entry="${grub_saved_name}"
else
   # calculate used name from number
   use_entry="$( grep -E -e '^menuentry' "${LUGE_GRUB_CFG}" | sed -r -n -e "$(( use_number + 1 ))p" )"
fi

# calculate which value to display or just display name
LUGE_grep=1
case "${LUGE_OUTPUT:-${1}}" in

   "num" | "number" )
      # just show the number
      unset LUGE_grep
      echo "${use_number}"
      ;;

   "kernel"|"vmlinuz" )
      # show kernel
      LUGE_regex="linux(16|32|64)"
      LUGE_awk_val='$2'
      ;;

   "initram" | "initrd" | "initramfs" )
      # show initram
      LUGE_regex="initrd|initram"
      LUGE_awk_val='$2'
      ;;

   *)
      # DEFAULT VALUE, so mistyped or not defined
      unset LUGE_grep
      echo "${use_entry}"
      ;;
esac

# show complicated value if necessary
if test -n "${LUGE_grep}" ;
then
   sed -n -r -e "/${use_entry}/,/^\s*\}/p" "${LUGE_GRUB_CFG}" | awk "/${LUGE_regex}/{print ${LUGE_awk_val}}"
fi

# exit cleanly
true

And an ansible playbook for myself:

---
# File: luge-tasks.yml
# Purpose: provides common tasks for displaying output from learn-used-grub-entry.sh
# Dependencies:
#    vars:
#       luge_script: '/etc/ansible/files/learn-used-grub-entry.sh'

- name: LUGE - learn lvm.conf filter
  shell: grep -E -e "^\s*(global_)?filter" {{ lvm_conf_file | default('/etc/lvm/lvm.conf') }} ; true
  args:
    warn: no
  changed_when: false
  register: lvm_conf

- name: LUGE - learn /boot value in fstab
  shell: grep -hE -e '\/boot' {{ etc_fstab_file | default('/etc/fstab') }} | grep -viE '^\s*(#|$)' ; true
  args:
    warn: no
  changed_when: false
  register: etc_fstab

- name: LUGE - learn grub menuentry to be used
  script: "{{ luge_script | default('/etc/ansible/files/learn-used-grub-entry.sh') }}"
  environment:
    LUGE_OUTPUT: name
  changed_when: false
  register: luge_menuentry

- name: LUGE - learn grub menuentry initram to be used
  script: "{{ luge_script | default('/etc/ansible/files/learn-used-grub-entry.sh') }}"
  environment:
    LUGE_OUTPUT: initram
  changed_when: false
  register: luge_initram

# this one will fail if the file does not exist
- name: LUGE - fail if selected initram is not valid initram file
  shell: lsinitrd "/boot{{ luge_initram.stdout_lines[0] }}" 1>/dev/null
  args:
    warn: no
  changed_when: false

- name: LUGE - capture raw info
  shell: echo "{{ item }}"
  loop:
  - "lvm.conf: {{ lvm_conf.stdout }}"
  - "fstab: {{ etc_fstab.stdout }}"
  - "menuentry: {{ luge_menuentry.stdout }}"
  - "initram: {{ luge_initram.stdout }}"
  register: stdout1
  changed_when: false

- name: LUGE - show useful info
  debug:
    msg: "{{ stdout1.results|map(attribute='stdout_lines')|flatten(levels=1) }}"

# info that is useful that is generated by the above statements
# - "{{ lvm_conf.stdout }}"
# - "{{ etc_fstab.stdout }}"
# - "{{ luge_menuentry.stdout }}"
# - "{{ luge_initram.stdout }}"

Comments