7

The highly rated Q&A How do I remove old kernel versions to clean up the boot menu? doesn't provide an easy way to selectively purge older kernels unless extra applications are installed ie Ubuntu-Tweak.

The Bash one-liner to delete only old kernels Q&A gives a "purge everything old" solution but I want to keep the last kernel in each generation. ie remove 4.7.1, 4.7.2... but keep 4.7.5.

Is there a way to scroll through a list of all installed kernels and select specific ones to purge? It should not allow purging of currently running kernel.

1 Answers1

6

The advantage of this answer is native Ubuntu Bash is used without installing third-party applications. Users of custom kernels who didn't use apt or dpkg can change this bash script to suit their needs.

Zenity based solution

Zenity provides a GUI interface to the terminal. Here it's used to process a list of kernels and select individual ones:

rm-kernels 1.png

The dialog title reports the number of kernels, their total size and the current kernel version booted. The current kernel is excluded from the title's totals and does not appear the kernel list.

The Modified Date is normally the date the kernel was released. On my system that date is "touched" every time the kernel is booted using a cron reboot script (How do you find out when a specific kernel version was last booted?).

For each kernel its size within the /boot directory is reported. Then the kernel's total size is summed for the three directories; /boot, /usr/src/kernel_version and /lib/modules/kernel_version.

If no parameter is passed to rm-kernels the total size is estimated and the title shows "Est. Total". This saves time running the du command which can take 30 seconds to 90 minutes depending on how many kernels you have and whether you have an SSD or an HDD. If you pass any parameter at all then du is used to obtain kernel sizes and the title shows "Real Total" as the sample screen above illustrates.

apt-get purge gives you chance to abort

You get to view everything that will be purged by apt purge and are given the option to proceed or abort:

The following packages will be REMOVED:
  linux-headers-4.4.0-78* linux-headers-4.4.0-78-generic*
  linux-headers-4.4.8-040408* linux-headers-4.4.8-040408-generic*
  linux-headers-4.6.3-040603* linux-headers-4.6.3-040603-generic*
  linux-headers-4.8.12-040812* linux-headers-4.8.12-040812-generic*
  linux-headers-4.9.0-040900* linux-headers-4.9.0-040900-generic*
  linux-headers-4.9.9-040909* linux-headers-4.9.9-040909-generic*
  linux-image-4.4.0-78-generic* linux-image-4.4.8-040408-generic*
  linux-image-4.6.3-040603-generic* linux-image-4.8.12-040812-generic*
  linux-image-4.9.0-040900-generic* linux-image-4.9.9-040909-generic*
  linux-image-extra-4.4.0-78-generic*
0 upgraded, 0 newly installed, 19 to remove and 1 not upgraded.
After this operation, 1,794 MB disk space will be freed.
Do you want to continue? [Y/n] 

apt purge reports 1,784 MB will be freed but the real total 2,379 MB. I don't know why it is different.

Rather than purging kernels one at a time and update-grub being repetitively called in time-consuming loop, the selections are purged all at once.

The Code

Copy this code to a file named rm-kernels in /usr/local/bin:

#!/bin/bash

# NAME: rm-kernels
# PATH: /usr/local/bin
# DESC: Provide zenity item list of kernels to remove

# DATE: Mar 10, 2017. Modified Aug 5, 2017.

# NOTE: Will not delete current kernel.

#       With 10 kernels on an SSD, empty cache from sudo prompt (#) using:
#       # free && sync && echo 3 > /proc/sys/vm/drop_caches && free
#       First time for `du` 34 seconds.
#       Second time for `du` 1 second.
#       With a magnetic hard disk, and empty memory cache:
#       the first `du` command averages about 20 seconds per kernel.
#       the second `du` command averages about 2.5 seconds per kernel.

# PARM: If any parm 1 passed use REAL kernel size, else use estimated size.
#       By default `du` is not used and estimated size is displayed.

# Must be running as sudo
if [[ $(id -u) != 0 ]]; then
    zenity --error --text "root access required. Use: sudo rm-kernels"
    exit 99
fi

OLDIFS="$IFS"
IFS="|"
choices=()

current_version=$(uname -r)

for f in /boot/vmlinuz*
do
    if [[ $f == *"$current_version"* ]]; then continue; fi # skip current version
    [[ $f =~ vmlinuz-(.*) ]]
    v=${BASH_REMATCH[1]}        # example: 4.9.21-040921-generic
    v_main="${v%-*}"            # example: 4.9.21-040921

    n=$(( n + 1 ))              # increment number of kernels

    # Kernel size in /boot/*4.9.21-040921-generic*
    s=$(du -ch /boot/*-$v* | awk '/total/{print $1}')

    if [[ $# -ne 0 ]] ; then    # Was a parameter passed?
        if [[ -d "/usr/src/linux-headers-"$v_main ]] ; then
             # Kernel headers size in /usr/src/*4.9.21-040921*
             s2=$(du -ch --max-depth=1 /usr/src/*-$v_main* | awk '/total/{print $1}')
        else
             s2="0M"            # Linux Headers are not installed
        fi
        # Kernel image size in /lib/modules/4.9.21-040921-generic*
        s3=$(du -ch --max-depth=1 /lib/modules/$v* | awk '/total/{print $1}')
    else
        # Estimate sizof of optional headers at 125MB and size of image at 220MB
        if [[ -d "/usr/src/linux-headers-"$v_main ]] ; then
             s2="125M"
        else
             s2="0M"            # Linux Headers are not installed
        fi
        s3="220M"
    fi

    # Strip out "M" provided by human readable option of du and add 3 sizes together
    c=$(( ${s//[^0-9]*} + ${s2//[^0-9]*} + ${s3//[^0-9]*} ))
    s=$(( ${s//[^0-9]*} )) # Strip out M to make " MB" below which looks nicer
    t=$(( t + c ))
    s=$s" MB"
    c=$c" MB"
    d=$(date --date $(stat -c %y $f) '+%b %d %Y') # Last modified date for display
    choices=("${choices[@]}" false "$v" "$d" "$s" "$c")
done

# Write Kernel version and array index to unsorted file
> ~/.rm-kernels-plain # Empty any existing file.
for (( i=1; i<${#choices[@]}; i=i+5 )) ; do
    echo "${choices[i]}|$i" >> ~/.rm-kernels-plain
done

# Sort kernels by version number
sort -V -k1 -t'|' ~/.rm-kernels-plain -o ~/.rm-kernels-sorted

# Strip out keys leaving Sorted Index Numbers
cut -f2 -d '|' ~/.rm-kernels-sorted > ~/.rm-kernels-ndx

# Create sorted array
SortedArr=()
while read -r ndx; do 
    end=$(( ndx + 4 ))
    for (( i=$(( ndx - 1 )); i<end; i++ )); do
        SortedArr+=("${choices[i]}")
    done
done < ~/.rm-kernels-ndx

rm ~/.rm-kernels-plain ~/.rm-kernels-sorted ~/.rm-kernels-ndx

if [[ $# -ne 0 ]] ; then    # Was a parameter passed?
    VariableHeading="Real Total"
else
    VariableHeading="Est. Total"
fi

# adjust width & height below for your screen 640x480 default for 1920x1080 HD screen
# also adjust font="14" below if blue text is too small or too large

choices=(`zenity \
        --title "rm-kernels - $n Kernels, Total: $t MB excluding: $current_version" \
        --list \
        --separator="$IFS" \
        --checklist --multiple \
        --text '<span foreground="blue" font="14">Check box next to kernel(s) to remove</span>' \
        --width=800 \
        --height=480 \
        --column "Select" \
        --column "Kernel Version Number" \
        --column "Modified Date" \
        --column "/boot Size" \
        --column "$VariableHeading" \
        "${SortedArr[@]}"`)
IFS="$OLDIFS"

i=0
list=""
for choice in "${choices[@]}" ; do
    if [ "$i" -gt 0 ]; then list="$list- "; fi # append "-" from last loop
    ((i++))

    short_choice=$(echo $choice | cut -f1-2 -d"-")
    header_count=$(find /usr/src/linux-headers-$short_choice* -maxdepth 0 -type d | wc -l)

    # If -lowlatency and -generic are purged at same time the _all header directory
    # remains on disk for specific version with no -generic or -lowlatency below.
    if [[ $header_count -lt 3 ]]; then
        # Remove all w.x.y-zzz headers
        list="$list""linux-image-$choice- linux-headers-$short_choice"
    else
        # Remove w.x.y-zzz-flavour header only, ie -generic or -lowlatency
        list="$list""linux-image-$choice- linux-headers-$choice" 
    fi

done

if [ "$i" -gt 0 ] ; then
     apt-get purge $list
fi

NOTE: You need to use sudo powers to save the file with your favorite editor.

To make file executable use:

sudo chmod +x /usr/local/bin/rm-kernels

Server Version

rm-kernels-server is the server version to selectively delete kernels all at once. Instead of a GUI (graphical) dialog box a text-based dialog box is used to select kernels to purge.

  • Before running the script you need to install the dialog function using:

    sudo apt install dialog

Dialog is in the default Ubuntu Desktop installation but not in Ubuntu Server.

Sample screen

rm-kernels-server 1

rm-kernels-server bash code

#!/bin/bash

# NAME: rm-kernels-server
# PATH: /usr/local/bin
# DESC: Provide dialog checklist of kernels to remove
#       Non-GUI, text based interface for server distro's.

# DATE: Mar 10, 2017. Modified Aug 5, 2017.

# NOTE: Will not delete current kernel.

#       With 10 kernels on an SSD, empty cache from sudo prompt (#) using:
#       # free && sync && echo 3 > /proc/sys/vm/drop_caches && free
#       First time for `du` 34 seconds.
#       Second time for `du` 1 second.
#       With a magnetic hard disk, and empty memory cache:
#       the first `du` command averages about 20 seconds per kernel.
#       the second `du` command averages about 2.5 seconds per kernel.

# PARM: If any parm 1 passed use REAL kernel size, else use estimated size.
#       By default `du` is not used and estimated size is displayed.

# Must be running as sudo
if [[ $(id -u) != 0 ]]; then
    echo "root access required. Use: sudo rm-kernels-server"
    exit 99
fi

# Must have the dialog package. On Servers, not installed by default
command -v dialog >/dev/null 2>&1 || { echo >&2 "dialog package required but it is not installed.  Aborting."; exit 99; }

OLDIFS="$IFS"
IFS="|"
item_list=() # Deviate from rm-kernels here.

current_version=$(uname -r)
i=0
for f in /boot/vmlinuz*
do
    if [[ $f == *"$current_version"* ]]; then continue; fi # skip current version
    [[ $f =~ vmlinuz-(.*) ]]
    ((i++)) # Item List
    v=${BASH_REMATCH[1]}        # example: 4.9.21-040921-generic
    v_main="${v%-*}"            # example: 4.9.21-040921

    n=$(( n + 1 ))              # increment number of kernels

    # Kernel size in /boot/*4.9.21-040921-generic*
    s=$(du -ch /boot/*-$v* | awk '/total/{print $1}')

    if [[ $# -ne 0 ]] ; then    # Was a parameter passed?
        if [[ -d "/usr/src/linux-headers-"$v_main ]] ; then
             # Kernel headers size in /usr/src/*4.9.21-040921*
             s2=$(du -ch --max-depth=1 /usr/src/*-$v_main* | awk '/total/{print $1}')
        else
             s2="0M"            # Linux Headers are not installed
        fi
        # Kernel image size in /lib/modules/4.9.21-040921-generic*
        s3=$(du -ch --max-depth=1 /lib/modules/$v* | awk '/total/{print $1}')
    else
        # Estimate sizof of optional headers at 125MB and size of image at 220MB
        if [[ -d "/usr/src/linux-headers-"$v_main ]] ; then
             s2="125M"
        else
             s2="0M"            # Linux Headers are not installed
        fi
        s3="220M"
    fi

    # Strip out "M" provided by human readable option of du and add 3 sizes together
    c=$(( ${s//[^0-9]*} + ${s2//[^0-9]*} + ${s3//[^0-9]*} ))
    s=$(( ${s//[^0-9]*} )) # Strip out M to make " MB" below which looks nicer
    t=$(( t + c ))
    s=$s" MB"
    c=$c" MB"
    d=$(date --date $(stat -c %y $f) '+%b %d %Y') # Last modified date for display
    item_list=("${item_list[@]}" "$i" "$v ! $d ! $s ! $c" off)
done

# Write Kernel version and array index to unsorted file
> ~/.rm-kernels-plain # Empty any existing file.
for (( i=1; i<${#item_list[@]}; i=i+3 )) ; do
    echo "${item_list[i]}|$i" >> ~/.rm-kernels-plain
done

# Sort kernels by version number
sort -V -k1 -t'|' ~/.rm-kernels-plain -o ~/.rm-kernels-sorted

# Strip out keys leaving Sorted Index Numbers
cut -f2 -d '|' ~/.rm-kernels-sorted > ~/.rm-kernels-ndx

# Create sorted array
SortedArr=()
i=1
while read -r ndx; do 
    SortedArr+=($i "${item_list[$ndx]}" "off")
    (( i++ ))
done < ~/.rm-kernels-ndx

rm ~/.rm-kernels-plain ~/.rm-kernels-sorted ~/.rm-kernels-ndx

cmd=(dialog --backtitle "rm-kernels-server - $n Kernels, Total: $t MB excluding: $current_version" \
    --title "Use space bar to toggle kernel(s) to remove" \
    --column-separator "!" \
    --separate-output \
    --ascii-lines \
    --checklist "         Kernel Version  ------  Modified Date /boot Size  Total" 20 70 15)

selections=$("${cmd[@]}" "${SortedArr[@]}" 2>&1 >/dev/tty)

IFS=$OLDIFS

if [ $? -ne 0 ] ; then
    echo cancel selected
    exit 1
fi

i=0
choices=()

for select in $selections ; do
    ((i++))
    j=$(( 1 + ($select - 1) * 3 ))
    choices[i]=$(echo ${SortedArr[j]} | cut -f1 -d"!")
done

i=0
list=""
for choice in "${choices[@]}" ; do
    if [ "$i" -gt 0 ]; then list="$list- "; fi # append "-" from last loop
    ((i++))

    short_choice=$(echo $choice | cut -f1-2 -d"-")
    header_count=$(find /usr/src/linux-headers-$short_choice* -maxdepth 0 -type d | wc -l)

    # If -lowlatency and -generic are purged at same time the _all header directory
    # remains on disk for specific version with no -generic or -lowlatency below.
    if [[ $header_count -lt 3 ]]; then
        # Remove all w.x.y-zzz headers
        list="$list""linux-image-$choice- linux-headers-$short_choice"
    else
        # Remove w.x.y-zzz-flavour header only, ie -generic or -lowlatency
        list="$list""linux-image-$choice- linux-headers-$choice" 
    fi

done

if [ "$i" -gt 0 ] ; then
    apt-get purge $list
fi

NOTE: In the call to dialog the directive --ascii-lines is passed to replace line-draw extended character set (which ssh doesn't like) with "+-----+" for drawing boxes. If you do not like this appearance you can use the --no-lines directive for no box at all. If you aren't using ssh you can delete the --ascii-lines and your display will be formated with line-draw characters:

rm-kernels-server line draw


July 28, 2017 Updates

The calculated size of each kernel was taken from /boot/*kernel_version* which were 5 files totaling ~50 MB. The formula has changed to include the files in /usr/src/*kernel_version* and /lib/modules/*kernel_version*. The calculated size for each kernel is now ~400 MB.

The default is to estimate the size of files for linux-headers at 125 MB and linux-image at 220 MB because du can be painfully slow unless files are in cached in memory. To get the real size using du pass any parameter to the script.

The total of all kernel sizes (excluding the current running version which cannot be removed) is now show in the title bar.

The dialog box used to display each Kernel's Last Access Date. This date can get mass overwritten for all kernels during backup or similar operations. The dialog box now shows the Modified Date instead.


August 5, 2017 Updates

The kernel list is now sorted by Kernel Version rather than alpha-numerically.

An additional column has been added for /boot size. In the graphical Zenity version the last column changes between "Real Total" and "Est. Total" (Estimated) depending on parameter 1 being passed or not.

  • I can not use your script, even though I would like to try it. My Ubuntu computers are mostly servers and I mostly use them via SSH terminal sessions. So your script doesn't work, giving: (zenity:16439): Gtk-WARNING **: cannot open display: I currently have 65 kernels installed and think I have good test case. – Doug Smythies Mar 11 '17 at 19:20
  • @DougSmythies I've started research using xdialog with --checklist options for selecting kernels in text-based environments. It will take me awhile to create alternate version as I already have a much larger project (adjust display brightness based on sunrise and sunset) to document and post in Q&A this weekend. – WinEunuuchs2Unix Mar 11 '17 at 19:42
  • What about linux-image-extra-, linux-signed-image-, and initrd.img-? – heynnema Mar 11 '17 at 19:45
  • O.K. Thanks. I only realized a few minutes ago that the question and answer were from the same person. After never getting the script I referred to in my comment on the question, I merely do a global purge after I move on to the next RC (Release Candidate) mainline kernel series. It just means that in general, I have a lot of kernels lying around. – Doug Smythies Mar 11 '17 at 19:47
  • @heynnema Thank you for your comment. I've replied via edit at bottom of answer. – WinEunuuchs2Unix Mar 11 '17 at 20:08
  • @heynnema makes a good point. Servers aside, I tried it on a desktop with 13 kernels installed, and I did not get the option to delete kernel 4.11-rc1, that I had compiled myself, (and it was not the boot kernel at the time). – Doug Smythies Mar 12 '17 at 00:58
  • @DougSmythies the script only finds kernels with vmlinuz... in the /boot directory. I'm not sure how a compiled release candidate (rc) kernel is setup differently than a mainline kernel. What do you get when you type ls /boot/vmlinuz* at the terminal? – WinEunuuchs2Unix Mar 12 '17 at 01:06
  • Yes, it is there: /boot/vmlinuz-4.11.0-rc1-stock /boot/vmlinuz-4.4.0-18-generic /boot/vmlinuz-4.4.0-51-generic /boot/vmlinuz-4.4.0-66-generic /boot/vmlinuz-4.4.0-14-generic /boot/vmlinuz-4.4.0-21-generic /boot/vmlinuz-4.4.0-53-generic /boot/vmlinuz-4.4.0-15-generic /boot/vmlinuz-4.4.0-31-generic /boot/vmlinuz-4.4.0-57-generic /boot/vmlinuz-4.4.0-17-generic /boot/vmlinuz-4.4.0-47-generic /boot/vmlinuz-4.4.0-64-generic – Doug Smythies Mar 12 '17 at 01:30
  • Aww it's because it doesn't end in -generic – WinEunuuchs2Unix Mar 12 '17 at 01:36
  • Yes, and low latency kernels will not either. – Doug Smythies Mar 12 '17 at 01:39
  • Yes low latency kernels are also excluded. Did you install your rc-stock kernel using apt-get install? Because the script could be modified however only kernels installed that way will be removed with apt-get purge. – WinEunuuchs2Unix Mar 12 '17 at 01:40
  • 1
    I would *highly* advise against using gksu gedit for this. First, Ubuntu no longer ships with gksu, and this can still cause problems. Just use plain old sudo nano, please. – Kaz Wolfe Mar 12 '17 at 19:06
  • @KazWolfe Personally I use pkexec gedit but other people won't have it until Ubuntu 17.04. I don't think the average person would like nano because it's text-based with no real mouse support. People who are using nano or vim have seen gksu gedit all over the net for years and are smart enough to know they can use nano or vim in it's place. – WinEunuuchs2Unix Mar 12 '17 at 19:41
  • Few remarks: You could use += operator to append to strings and arrays in Bash. You do not need to append "-" to arguments for apt-get purge. Why not just use apt-get purge $list instead of echo "dummy- $list" | xargs bash -c '</dev/tty apt-get purge "$@"'? – jarno Mar 12 '17 at 22:02
  • @jarno I tried apt-get purge $list and ${list[@]} and other techniques the first time. I can't remember what broke but I think bash treated it as one long string with spaces, rather than arguments separated by spaces. I've already got plans to compact the code in the next version so I'll revisit your suggestions then. Thanks for the tips :) – WinEunuuchs2Unix Mar 12 '17 at 22:41
  • It will be treated as one long string with spaces, if you double quote it. – jarno Mar 13 '17 at 09:42
  • Duh good point. I've been double quoting myself to death. Thanks :) – WinEunuuchs2Unix Mar 13 '17 at 10:11
  • In my experience dialog can draw the line-draw characters fine over ssh connection, so --ascii-lines might not be necessary. But maybe in some configuration it does not work. – jarno Mar 22 '17 at 16:10
  • In my script I use whiptail by default, since it is installed by default, but it does not have --column-separator so it seems hard to use multiple columns with it. – jarno Mar 22 '17 at 16:20
  • @jarno Sorry for delay. I had originally tried to post on my phone which didn't allow it and then forgot about it for a few days.... It's good to know about SSH and line drawing. As I don't have SSH I can't test it myself. The --coumn-seperaror of zenity and dialog are nice for sure. Since completing this project though I've moved on to yad which blows zenity out of the water in the functionality department. If you are interested in the newest project: http://askubuntu.com/questions/894888/bash-template-to-use-zenity-or-yad-to-insert-edit-delete-records-in-a-file – WinEunuuchs2Unix Mar 25 '17 at 17:55
  • Thanks for your continued work on this. I am trying the newer version now. The added du commands are taking a horrendous amount of time. I'm ~15 minutes into execution and the second du command only started a few minutes ago. I have somewhere around 80 kernels installed at the moment (i.e. I was about to run this script again anyhow). More later. – Doug Smythies Jul 28 '17 at 13:36
  • In the end it was ~30 minutes before the menu came up. I aborted and went back to the previous version, flushed memory to remove any caching effects, it was only a few seconds until the menu came up. I think I'll stay with the previous version. Anyway, I aborted again, so as to keep a large number of kernels for now and in case you want me to try anything. – Doug Smythies Jul 28 '17 at 13:53
  • @DougSmythies I've revised the code to NOT call du. Instead it estimates the size of linux-headers (if installed) at 125MB and linux-image at 220MB. If any parameter is passed it will calculate the real size using du. Hopefully it's perfect now as the same answer is posted in https://askubuntu.com/questions/2793/how-do-i-remove-old-kernel-versions-to-clean-up-the-boot-menu/892096#892096 and https://askubuntu.com/questions/142926/cant-upgrade-due-to-low-disk-space-on-boot/913597#913597. In hind-sight I should have only posted it here and pinged you for input. Thanks for your testing :) – WinEunuuchs2Unix Jul 28 '17 at 22:40
  • Many times the size occupied by kernels under /boot is most important, as separate /boot is usually small limiting the number of kernels that fit in system. – jarno Aug 01 '17 at 19:29
  • @jarno You make an excellent point. You would vote to restore the original format. What I'll do is make two columns: /boot Size and Total Size. The second column heading will be context sensitive though and and display Total Size or Total Est.. I need to totally revamp the documentation and screen shots so it'll be a weekend project. Thanks for your input! – WinEunuuchs2Unix Aug 02 '17 at 00:13
  • @jarno I've created two file size total columns: one for /boot and one for everything. I've also sorted the kernels by Version Number collating sequence rather than Alphanumerically. – WinEunuuchs2Unix Aug 06 '17 at 13:36
  • @DougSmythies I think you will be interested in the changes to rm-kernels-server made yesterday. – WinEunuuchs2Unix Aug 06 '17 at 13:37
  • I don't care about the files sizes and such. I'll only run it without a parameter, i.e. without running the extra overhead commands. I do like the sort order of the list now. Thanks for your continued work on this. – Doug Smythies Aug 06 '17 at 22:47
  • A small point: The sizes column seems to include all kernels with package names that are longer, but the same until they are longer. What, you ask? Example: 4 kernels: 4.9.0; 4.9.0-stock, 4.9.0-test, 4.9.0-test-test. The size columns lists: 196 MB for 4.9.0; and 98 MB for 4.9.0-test. Actually they are all 49 MB. (as previously mentioned, I don't actually care about file sizes and such). See here to understand why I have these kernel names. I am trying jarno's version. – Doug Smythies Aug 31 '17 at 01:00
  • @DougSmythies That's because it expects Ubuntu style naming where 4.9.0 by itself is invalid. It needs a single suffix like -generic or -lowlatency to add up file sizes correctly. I'll keep this in mind for next version enhancements though. Thanks :) – WinEunuuchs2Unix Aug 31 '17 at 10:06
  • Just F.Y.I. the way I created the 4.9.0 one was by NOT specifying a localversion in the compile command. i.e. I did this: make -j9 olddefconfig bindeb-pkg instead of this make -j9 olddefconfig bindeb-pkg LOCALVERSION=-test-test. I did it only for testing purposes. – Doug Smythies Aug 31 '17 at 14:15
  • After reading all the comments... was there ever a fix for this?
    `No protocol specified`
    `** (zenity:30808): WARNING **: Could not open X display`
    `No protocol specified`
    `(zenity:30808): Gdk-ERROR **: error: XDG_RUNTIME_DIR not set in the environment.`
    
    – Seek Truth Dec 01 '17 at 17:16
  • @SeekTruth Are you using Ubuntu 17.10 with Wayland windows? If so Zenity might crash because it's a gui and Wayland doesn't let you use a gui with sudo. If so try rm-kernels-server which is sudo character based. If you're not using Wayland are you using ssh? – WinEunuuchs2Unix Dec 02 '17 at 02:57
  • @WinEunuuchs2Unix nope 14.04 LTS Just found solution here! Which shows pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY rm-kernels to run it instead of sudo rm-kernels. – Seek Truth Dec 03 '17 at 17:17
  • @SeekTruth thanks for your comments that will help others in the same zenity error situations. I already had pxexec setup for nautilus and gedit but don't recall any zenity errors with root privaledges. – WinEunuuchs2Unix Dec 03 '17 at 17:42