#!/usr/bin/env bash set -o pipefail cleanup() { rm -f "${tmp_container[@]}" } insert_date() { while read do local date_value date_value="$(date +"%b %d %T %s.%N")" echo "${date_value} ${REPLY}" done } fatal_error_handler() { local result="$?" local p_message="$1" local pid="${BASHPID}" (exit "${result}") || { ( cd "$(dirname "${BASH_SOURCE[1]}")" echo -n "${FUNCNAME[0]}: $(echo | insert_date)${PWD}/${BASH_SOURCE[1]##*/}:${BASH_LINENO[0]} ${FUNCNAME[1]}() PID(${pid})" ) [ "${p_message}" != "" ] && echo -n " ${p_message}" echo return "${result}" } >&2 } version_test_gt() { local version_a="$1" local version_b="$2" dpkg --compare-versions "${version_a}" gt "${version_b}" } get_current_kernel_version() { local p_dpkg_output="$1" local current_kernel_version current_kernel_version="linux-image-$(uname -r)" current_kernel_version="$(awk '$2=="'${current_kernel_version}'" {print $3}' <<< "${p_dpkg_output}")" || fatal_error_handler || return [ "${current_kernel_version}" != "" ] || fatal_error_handler || return echo "${current_kernel_version}" } is_gui_required() { if ! tty &> /dev/null then echo "true" else echo "false" fi } main() { local dpkg_output dpkg_output="$(dpkg -l 'linux-image-[0-9]*' | awk '$1=="ii"')" || fatal_error_handler || return [ "${dpkg_output}" != "" ] || fatal_error_handler || return local version_to_keep_container version_to_keep_container=($(awk '{print $3}' <<< "${dpkg_output}")) || fatal_error_handler || return [ 0 -lt "${#version_to_keep_container[@]}" ] || fatal_error_handler || return local idx1 for ((idx1=0; idx1<${#version_to_keep_container[@]}-1; ++idx1)) do local idx2 for ((idx2=idx1+1; idx2<${#version_to_keep_container[@]}; ++idx2)) do if version_test_gt "${version_to_keep_container[idx1]}" "${version_to_keep_container[idx2]}" then local tmp="${version_to_keep_container[idx1]}" version_to_keep_container[idx1]="${version_to_keep_container[idx2]}" version_to_keep_container[idx2]="${tmp}" fi done done version_to_keep_container=($( { ( IFS=$'\n' echo "${version_to_keep_container[*]}" ) | tail -2 || fatal_error_handler || return get_current_kernel_version "${dpkg_output}" || fatal_error_handler || return } | sort -u)) || fatal_error_handler || return ((1 <= "${#version_to_keep_container[@]}" && "${#version_to_keep_container[@]}" <= 3)) || fatal_error_handler || return dpkg_output="$(dpkg -l 'linux-headers-*' 'linux-image-*' | awk '$1=="ii"')" || fatal_error_handler || return [ "${dpkg_output}" != "" ] || fatal_error_handler || return for ((idx1=0; idx1<${#version_to_keep_container[@]}; ++idx1)) do dpkg_output="$(awk '$3!="'${version_to_keep_container[idx1]}'"' <<< "${dpkg_output}")" || fatal_error_handler || return done dpkg_output="$(awk '$2!="linux-headers-generic"' <<< "${dpkg_output}")" || fatal_error_handler || return dpkg_output="$(awk '$2!="linux-image-generic"' <<< "${dpkg_output}")" || fatal_error_handler || return local package_to_remove_container if [ "${dpkg_output}" != "" ] then package_to_remove_container+=($(awk '{print $2}' <<< "${dpkg_output}")) || fatal_error_handler || return fi dpkg_output="$(dpkg -l | awk '$1=="rc"')" || fatal_error_handler || return if [ "${dpkg_output}" != "" ] then package_to_remove_container+=($(awk '{print $2}' <<< "${dpkg_output}")) || fatal_error_handler || return fi if [ 0 -lt "${#package_to_remove_container[@]}" ] then if [ "${gui_required}" = "true" ] then (IFS=$'\n';echo "${package_to_remove_container[*]}") | LANG="${language}" zenity --list --title "${title}" --text "${text}" --column "${column}" &> /dev/null || return 0 else echo "${text}" (IFS=$'\n';echo "${package_to_remove_container[*]}") echo -n "${choice}" read [ "${REPLY}" != "y" ] && [ "${REPLY}" != "o" ] && return 0 fi if [ "${gui_required}" = "true" ] then local password password="$(LANG="${language}" zenity --title "${title}" --password)" || return 0 sudo -S -- apt-get -y purge "${package_to_remove_container[@]}" <<< "${password}" || fatal_error_handler || return sudo -S -- apt-get -y autoclean <<< "${password}" || fatal_error_handler || return sudo -S -- apt-get -y clean <<< "${password}" || fatal_error_handler || return sudo -S -- apt-get -y autoremove <<< "${password}" || fatal_error_handler || return unset password else sudo -- apt-get -y purge "${package_to_remove_container[@]}" || fatal_error_handler || return sudo -- apt-get -y autoclean || fatal_error_handler || return sudo -- apt-get -y clean || fatal_error_handler || return sudo -- apt-get -y autoremove || fatal_error_handler || return fi if [ "${gui_required}" = "true" ] then LANG="${language}" zenity --title "${title}" --info --text "${text2}" --no-wrap else echo "${text2}" fi fi } if [ "$0" = "${BASH_SOURCE[0]}" ] then trap cleanup EXIT declare -r gui_required="$(is_gui_required)" if [ "${gui_required}" = "true" ] then tmp_container+=("$(mktemp -u)") declare -r logfile="${tmp_container[${#tmp_container[@]}-1]}" exec &> "${logfile}" fi declare -r language="${LANG}" if [ "${language:0:5}" = "fr_FR" ] then declare -r title="Nettoyeur du système" declare -r text="Voulez vous supprimer les paquets ci-dessous ?" declare -r text2="Le système a été nettoyé avec succès." declare -r column="Nom du paquet" declare -r choice="Choix (o/n) : " declare -r text3="Contenu du fichier : \"${logfile}\"" else declare -r title="System cleaner" declare -r text="Do you want to remove packages below?" declare -r text2="System has been successfully cleaned." declare -r column="Package name" declare -r choice="Choice (y/n): " declare -r text3="Content of file: \"${logfile}\"" fi if [ "${gui_required}" = "true" ] then echo "${text3}" fi LANG="C" main "$@" || fatal_error_handler || [ "${gui_required}" = "false" ] || LANG="${language}" zenity --title "${title}" --text-info --filename "${logfile}" fi