#!/bin/bash # ====================================================================== # # NAGIOS CLIENT CHECK :: check available package updates # requires no root for yum ... apt I must verify # # ---------------------------------------------------------------------- # # ah=axel.hahn@iml.unibe.ch # ds=daniel.schueler@iml.unibe.ch # # 2016-12-23 v0.3 ah,ds # 2018-12-18 v1.0 ah added check for auto update (IML specific) # 2019-03-26 v1.1 ah fix apt-get (not all constellations worked) # 2019-04-29 v1.2 ah yum: supress error channel output (task #2959) # 2020-03-05 v1.3 <axel.hahn@iml.unibe.ch> switch to ph.* helper functions # 2020-03-11 v1.4 <axel.hahn@iml.unibe.ch> add -c -w limits; added perfdata (yum) # 2021-05-11 v1.4 <axel.hahn@iml.unibe.ch> added centos8 support # 2021-08-20 v1.5 <martin.gasser@iml.unibe.ch> bug fixing - missing sudo in yum command # 2021-12-16 v1.6 <axel.hahn@iml.unibe.ch> show filtered overview # ====================================================================== . `dirname $0`/inc_pluginfunctions typeset -i iCount=0 tmpfile=/tmp/packages2install.log cronfile=/etc/cron.d/system-updater MYhost="localhost" # ---------------------------------------------------------------------- # functions # ---------------------------------------------------------------------- function showAutoupdate(){ ls ${cronfile} >/dev/null 2>&1 if [ $? -eq 0 ]; then echo Autoupdate ON grep "\ \-r" ${cronfile} >/dev/null 2>&1 if [ $? -eq 0 ]; then echo Autoreboot ON else echo Autoreboot OFF fi else echo Autoupdate OFF fi } # execute a local or a remote command function _exec(){ if [ ${MYhost} = "localhost" ]; then eval "$1" else ${MYsshprefix}${MYhost} "$1" fi } # apply filter on incoming piped data # filter is a param with spaced keywords that will be transformed # to a regex # param1 text if filter keywords (seperated by space) function _filterPkg(){ local _filter=$( echo $1 | tr " " "|" ) grep -E "^($_filter)" } # autodetect a package manager using which with # a list of known pkg managers function detectPkgManager(){ local _list="apt yum pamac" local out=$( _exec "which $_list 2>/dev/null" ) for mypkg in $_list do echo "$out" | grep "/$mypkg" > /dev/null && echo $mypkg done } # Debian like Linux # - Debian 11 function pkgApt(){ local sum=$( _exec "sudo apt-get -u upgrade --assume-no" ) # detect number of line containing "The following packages will be upgraded:" typeset -i local iStart=$( echo "$sum" | grep -n '^The following packages will be upgraded:' | cut -f 1 -d ':' ) if [ $iStart -eq 0 ]; then echo "Nothing to install" else # show packages = text starting with 2 spaces below start line # packages are delimited with space -> replace with new line echo "$sum" | sed -n $iStart,\$p | grep "^\ \ " | sed "s#^\ \ ##g" | tr " " "\n" fi } # Arch Linux, Manjaro function pkgPamac(){ _exec "pamac checkupdates | grep -- '->'" } # RedHat like Linux # - Centos 8 function pkgYum(){ local sum=$( _exec "sudo dnf check-update" ) local iStart=3 # detect number of line containing "Obsoleting Packages" typeset -i iEnd=$( echo "$sum" | grep -n '^Obsoleting Packages' | cut -f 1 -d ':' )-1 local sEnd=$iEnd test "$iEnd" = "-1" && sEnd='$' echo "$sum" | sed -n ${iStart},${sEnd}p # echo "show lines ${iStart} -> ${sEnd}" } # check updates with apt and exit script function checkApt(){ # bug #2818 sudo apt-get -v >/dev/null if [ $? -ne 0 ]; then ph.setStatus "error" echo "ERROR: failed to run apt-get" echo "OUTPUT is:" sudo apt-get -v else summary=`ph.execIfReady "sudo apt-get -u upgrade --assume-no | grep installed | grep upgraded" ` # example output: # 0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded. typeset -i local iPkg2Update=`echo $summary | cut -f 1 -d " "` ph.setStatusByLimit ${iPkg2Update} ${iWarnLimit} ${iCriticalLimit} ph.perfadd "updates-available" "${iPkg2Update}" ${iWarnLimit} ${iCriticalLimit} # --- output ph.status "$summary" echo "[apt]" echo fi } # check updates with yum and exit script function checkYum(){ local _yumout=/tmp/yumoutput.log # summary=`ph.execIfReady "/usr/bin/yum --security check-update 2>&1 | fgrep 'security'" ` # summary=`ph.execIfReady "/usr/bin/yum --security check-update 2>&1 | fgrep 'security'" ` ph.execIfReady "sudo /usr/bin/yum --security check-update > $_yumout 2>&1" local summary=$( cat $_yumout | grep security ) test -z "$summary" && summary='no data .. no packages to install' # example outputs: # I No packages needed for security; 223 packages available # II 2 package(s) needed for security, out of 237 available typeset -i local iPkgSecurity=` echo $summary | cut -f 1 -d ' ' | sed "s#[^0-9]##g"` typeset -i local iPkg2Update=` echo $summary | cut -f 2- -d ' ' | sed "s#[^0-9]##g"` # step I: check limits with packages to update: ph.setStatusByLimit ${iPkg2Update} ${iWarnLimit} ${iCriticalLimit} # step II: security packages switch to "critical" # remark: a warn level does not exist if [ ${iPkgSecurity} -ne 0 ]; then ph.setStatus "critical" fi ph.perfadd "updates-available" "${iPkg2Update}" ${iWarnLimit} ${iCriticalLimit} ph.perfadd "updates-security" "${iPkgSecurity}" 1 1 ph.status "$summary" echo "[yum]" cat $_yumout rm -f yumout echo } # ---------------------------------------------------------------------- # main # ---------------------------------------------------------------------- # set default / override from command line params typeset -i iWarnLimit=` ph.getValueWithParam 1 w "$@"` typeset -i iCriticalLimit=` ph.getValueWithParam 200 c "$@"` # ----- try package manager apt pgkman=$( detectPkgManager ) case $pgkman in "apt") pkgstatus=$( checkApt ) pkgsum=$( pkgApt ) ;; "pamac") pkgstatus="" pkgsum=$( pkgPamac ) ;; "yum") pkgstatus=$( checkYum ) pkgsum=$( pkgYum ) ;; *) ph.abort "UNKNOWN: package manager [$pgkman] was not detected or is not supported yet." ;; esac echo "$pkgstatus" echo # filtered package view if [ ! -z "$pkgsum" ]; then typeset -i iTotal=$( echo "$pkgsum" | wc -l ) typeset -i iFound=0 # show filtered view for filterfile in $( ls -1 $0-data/*txt | sort ) do filtername=$( echo $filterfile | rev | cut -f 1 -d "/" | rev | sed "s#.txt\$##g" | sed "s#^[0-9]*_##g" ) filterdata=$( cat ${filterfile} | grep "^[a-zA-Z]" ) out=$( echo "$pkgsum" | _filterPkg "${filterdata}" ) typeset -i iCount=$( echo "$out" | grep "." | wc -l ) test $iCount -ne 0 && ( echo --- $( echo "$filtername" | sed "s#MYfilter##g" ): $iCount echo "$out" | nl; echo ) iFound=$iFound+$iCount done # show count of non matching packages typeset -i iOther=$iTotal-$iFound if [ $iFound -eq 0 ]; then echo "No package matched a group filter." else echo "Other packages: $iOther" fi # total packages echo Total packages to update [$pgkman]: $iTotal echo fi showAutoupdate ph.exit # ----------------------------------------------------------------------