Skip to content

Commit 261dc22

Browse files
authored
Merge pull request #97 from nielsk/master
2 parents 365a391 + 0a6d38c commit 261dc22

1 file changed

Lines changed: 123 additions & 66 deletions

File tree

  • agents/plugins

agents/plugins/yum

100755100644
Lines changed: 123 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Set the version to be captured in newer versions of CheckMK Inventory
33
CMK_VERSION="0.0.0"
44

5-
if [ -z $MK_VARDIR ]; then
5+
if [ -z "$MK_VARDIR" ]; then
66
echo "ERROR: Unable to load ENV variables"
77
exit 2
88
fi
@@ -15,21 +15,52 @@ CACHE_YUM_UPDATE=$MK_VARDIR/cache/yum_update.cache
1515
CACHE_PREV_UPTIME=$MK_VARDIR/cache/yum_uptime.cache
1616
LAST_UPDATE_TIMESTAMP=-1
1717

18-
# Check which major version we are running so we can run appropriate commands
18+
# Check which distribution and major version we are running
1919
if [ -f "/etc/os-release" ]; then
20-
MAJOR_VERSION=$(grep -oP '(?<=^VERSION_ID=").*(?=")' /etc/os-release | cut -d '.' -f 1)
20+
MAJOR_VERSION=$(awk -F'=' '/^VERSION_ID=/ {gsub(/"/,"",$2); split($2,a,"."); print a[1]}' /etc/os-release)
21+
DISTRO_ID=$(awk -F'=' '/^ID=/ {gsub(/"/,"",$2); print $2}' /etc/os-release)
2122
else
2223
MAJOR_VERSION=0
24+
DISTRO_ID="unknown"
2325
fi
2426

25-
# get current yum state - use cache directory contents as fingerprint
27+
# Determine which package manager to use based on distribution and availability
28+
PKG_MGR=""
29+
HISTORY_CMD=""
30+
LIST_CMD=""
31+
SECURITY_SUPPORTED=0
32+
33+
# Check for dnf5 first (Fedora 41+)
34+
if command -v dnf5 >/dev/null 2>&1; then
35+
PKG_MGR="dnf5"
36+
HISTORY_CMD="dnf5 history list"
37+
LIST_CMD="dnf5 list --upgrades"
38+
SECURITY_SUPPORTED=1 # dnf5 supports security updates via check-upgrade --security
39+
# Check for regular dnf (Fedora 22+ up to 40, CentOS 8+)
40+
elif command -v dnf >/dev/null 2>&1; then
41+
PKG_MGR="dnf"
42+
HISTORY_CMD="dnf history list"
43+
LIST_CMD="dnf list updates"
44+
SECURITY_SUPPORTED=1
45+
# Fall back to yum (CentOS/RHEL 6-7)
46+
elif command -v yum >/dev/null 2>&1; then
47+
PKG_MGR="yum"
48+
HISTORY_CMD="yum history list"
49+
LIST_CMD="yum list updates"
50+
SECURITY_SUPPORTED=1
51+
else
52+
echo "ERROR: No supported package manager found (yum, dnf, or dnf5)"
53+
exit 2
54+
fi
55+
56+
# get current package manager state - use cache directory contents as fingerprint
2657
YUM_CURRENT="$(ls -lR /var/cache/{yum,dnf}/ 2>/dev/null)"
2758

2859
# check if cached listing of /var/cache/yum already exists - create empty one otherwise
29-
if [ ! -e $CACHE_YUM_UPDATE ]
60+
if [ ! -e "$CACHE_YUM_UPDATE" ]
3061
then
31-
touch $CACHE_YUM_UPDATE
32-
elif [ ! -f $CACHE_YUM_UPDATE ] || [ -L $CACHE_YUM_UPDATE ]
62+
touch "$CACHE_YUM_UPDATE"
63+
elif [ ! -f "$CACHE_YUM_UPDATE" ] || [ -L "$CACHE_YUM_UPDATE" ]
3364
then
3465
# something is wrong here...
3566
echo "ERROR: invalid cache file"
@@ -40,10 +71,10 @@ else
4071
fi
4172

4273
# check if cached check result already exists and is nothing but a file
43-
if [ ! -e $CACHE_RESULT_CHECK ]
74+
if [ ! -e "$CACHE_RESULT_CHECK" ]
4475
then
45-
touch $CACHE_RESULT_CHECK
46-
elif [ ! -f $CACHE_RESULT_CHECK ] || [ -L $CACHE_RESULT_CHECK ]
76+
touch "$CACHE_RESULT_CHECK"
77+
elif [ ! -f "$CACHE_RESULT_CHECK" ] || [ -L "$CACHE_RESULT_CHECK" ]
4778
then
4879
# something is wrong here...
4980
echo "ERROR: invalid cache file"
@@ -54,11 +85,11 @@ fi
5485
RUNNING_SECS=$(cat /proc/uptime | cut -d" " -f1 | cut -d"." -f1)
5586

5687
# check if cache file with previously seen uptime is existing - create one otherwise
57-
if [ ! -e $CACHE_PREV_UPTIME ]
88+
if [ ! -e "$CACHE_PREV_UPTIME" ]
5889
then
59-
echo 0 > $CACHE_PREV_UPTIME
90+
echo 0 > "$CACHE_PREV_UPTIME"
6091
PREV_UPTIME=0
61-
elif [ ! -f $CACHE_PREV_UPTIME ] || [ -L $CACHE_PREV_UPTIME ]
92+
elif [ ! -f "$CACHE_PREV_UPTIME" ] || [ -L "$CACHE_PREV_UPTIME" ]
6293
then
6394
# something is wrong here...
6495
echo "ERROR: invalid cache file"
@@ -67,103 +98,129 @@ else
6798
# get cached information
6899
PREV_UPTIME=$(cat "$CACHE_PREV_UPTIME")
69100
# save current uptime
70-
echo $RUNNING_SECS > $CACHE_PREV_UPTIME
101+
echo "$RUNNING_SECS" > "$CACHE_PREV_UPTIME"
71102
fi
72103

73104
# check if current uptime is lower than cached last seen uptime to detect reboot
74105
if (( RUNNING_SECS < PREV_UPTIME ))
75106
then
76107
# remove pre-reboot cache which requires reboot
77-
rm -f $CACHE_RESULT_CHECK
108+
rm -f "$CACHE_RESULT_CHECK"
78109
# create empty check cache
79-
touch $CACHE_RESULT_CHECK
110+
touch "$CACHE_RESULT_CHECK"
80111
fi
81112

82113
echo "<<<yum>>>"
83114

84115
# compare current and cached yum information
85116
# Update cached data if YUM fingerprint has changed OR machine has recently rebooted.
86-
if [ "$YUM_CURRENT" != "$YUM_CACHED" ] || [ ! -s $CACHE_RESULT_CHECK ]
117+
if [ "$YUM_CURRENT" != "$YUM_CACHED" ] || [ ! -s "$CACHE_RESULT_CHECK" ]
87118
then
88119
count=0
89-
while [ -n "$(pgrep -f "python (/usr|)/bin/(yum|dnf)")" ]; do
90-
if [ $count -eq 3 ]; then
91-
echo "ERROR: Tried to run yum for 30 secs but another yum instance was running"
92-
exit 2
93-
else
94-
((count++))
95-
sleep 10
96-
fi
97-
done
98-
LATEST_KERNEL=$(yum -q -C --noplugins --debuglevel 0 list installed | egrep "^(vz)?kernel(|-(uek|ml|lt))\." | grep "\." | tail -n1 | awk '{print $2};')
120+
# Check for running package manager processes
121+
while [ -n "$(pgrep -f "(python|/usr/bin/).*/(yum|dnf)" | head -1)" ]; do
122+
if [ $count -eq 3 ]; then
123+
echo "ERROR: Tried to run $PKG_MGR for 30 secs but another package manager instance was running"
124+
exit 2
125+
else
126+
((count++))
127+
sleep 10
128+
fi
129+
done
130+
131+
# Check for kernel updates - different approach for different package managers
132+
if [ "$PKG_MGR" = "dnf5" ]; then
133+
# dnf5 has different output format - get only main kernel package, not kernel-core or kernel-modules
134+
LATEST_KERNEL=$(dnf5 list --installed 2>/dev/null | grep -E "^kernel\.x86_64" | tail -n1 | awk '{print $2}')
135+
else
136+
# Traditional yum/dnf approach
137+
LATEST_KERNEL=$($PKG_MGR -q -C --noplugins list installed 2>/dev/null | egrep "^(vz)?kernel(|-(uek|ml|lt))\." | grep "\." | tail -n1 | awk '{print $2}')
138+
fi
139+
99140
RUNNING_KERNEL=$(cat /proc/version | awk '{print $3}' | sed 's/.x86_64//g')
100141
if [[ "$RUNNING_KERNEL" == "$LATEST_KERNEL"* ]]
101142
then
102143
BOOT_REQUIRED="no"
103144
else
104145
BOOT_REQUIRED="yes"
105146
fi
106-
UPDATES=$(waitmax 25 /usr/bin/yum -C --noplugins --quiet list updates | grep "\." | cut -d' ' -f1 | wc -l || echo "-1")
107-
# check if --security is available
108-
# Updated the timeout for the initial security list validation because it takes longer than 10 seconds on many machines
109-
waitmax 25 /usr/bin/yum -C --noplugins --quiet --security list updates > /dev/null 2>&1
110-
if [ $? -eq 0 ]
111-
then
112-
SECURITY_UPDATES=$(waitmax 25 /usr/bin/yum -C --noplugins --quiet --security list updates | grep "\." | cut -d' ' -f1 | wc -l || echo "-1")
147+
148+
# Count available updates - different commands for different package managers
149+
if [ "$PKG_MGR" = "dnf5" ]; then
150+
UPDATES=$(waitmax 25 dnf5 list --upgrades 2>/dev/null | grep -E "^[a-zA-Z]" | wc -l || echo "-1")
113151
else
114-
# --security not supported with this yum version
115-
# maybe the yum-plugin-security package is needed (RH 6)
116-
SECURITY_UPDATES="-2"
152+
UPDATES=$(waitmax 25 $PKG_MGR -C --noplugins --quiet list updates 2>/dev/null | grep "\." | cut -d' ' -f1 | wc -l || echo "-1")
117153
fi
118154

119-
# Check last time of installed Updates from yum history
120-
# Added "list all" to the history command as in situations where 20 or more RPM installs have been completed (non updates
121-
# yum commands) have been run, the script will incorrectly report that the server has never updated
122-
# Yum only lists 20 of the last actions when using only the "history" command.
123-
124-
# Switch command based on which Major version we are running
125-
if [ "$MAJOR_VERSION" -ge 8 ]; then
155+
# Check for security updates if supported
156+
if [ $SECURITY_SUPPORTED -eq 1 ]; then
157+
if [ "$PKG_MGR" = "dnf5" ]; then
158+
# dnf5 uses different command for security updates
159+
SECURITY_UPDATES=$(waitmax 25 dnf5 -C --quiet check-upgrade --security 2>/dev/null | grep -E "^[a-zA-Z0-9]" | wc -l || echo "-1")
160+
else
161+
# Test if --security is available for traditional yum/dnf
162+
waitmax 25 $PKG_MGR -C --noplugins --quiet --security list updates > /dev/null 2>&1
163+
if [ $? -eq 0 ]; then
164+
if [ "$PKG_MGR" = "dnf" ]; then
165+
SECURITY_UPDATES=$(waitmax 25 dnf -C --noplugins --quiet --security list updates 2>/dev/null | grep "\." | cut -d' ' -f1 | wc -l || echo "-1")
166+
else
167+
SECURITY_UPDATES=$(waitmax 25 yum -C --noplugins --quiet --security list updates 2>/dev/null | grep "\." | cut -d' ' -f1 | wc -l || echo "-1")
168+
fi
169+
else
170+
# --security not supported with this version
171+
SECURITY_UPDATES="-2"
172+
fi
173+
fi
174+
else
175+
# Package manager doesn't support security updates
176+
SECURITY_UPDATES="-2"
177+
fi
126178

127-
LAST_UPDATE_TIMESTAMP=$(/usr/bin/yum -C --quiet --noplugins history list | awk '{if(NR>2)print}' | grep ' U \|Upgrade\|Update' | cut -d '|' -f3 | head -n 1 | date -f - +"%s" || echo "-1")
179+
# Check last time of installed Updates from history
180+
if [ "$PKG_MGR" = "dnf5" ]; then
181+
# dnf5 has different history output format - look for upgrade/update actions, not download
182+
LAST_UPDATE_TIMESTAMP=$(dnf5 history list 2>/dev/null | awk '/upgrade --refresh|update[^-]|update$/ {print $5" "$6}' | head -n1 | date -f - +"%s" 2>/dev/null || echo "-1")
183+
elif [ "$DISTRO_ID" = "fedora" ] || [ "$DISTRO_ID" = "centos" -a "$MAJOR_VERSION" -ge 8 ] || [ "$DISTRO_ID" = "rhel" -a "$MAJOR_VERSION" -ge 8 ]; then
184+
# Modern dnf/yum with different history format
185+
LAST_UPDATE_TIMESTAMP=$($PKG_MGR -C --quiet --noplugins history list 2>/dev/null | awk '{if(NR>2)print}' | grep -E ' U | Upgrade| Update' | head -n1 | awk '{print $3}' | date -f - +"%s" 2>/dev/null || echo "-1")
128186
else
129-
LAST_UPDATE_TIMESTAMP=$(/usr/bin/yum -C --quiet --noplugins history list all| awk '{if(NR>2)print}' | grep ' U \|Upgrade\|Update' | cut -d '|' -f3 | head -n 1 | date -f - +"%s" || echo "-1")
187+
# Legacy yum (CentOS/RHEL 6-7)
188+
LAST_UPDATE_TIMESTAMP=$(yum -C --quiet --noplugins history list all 2>/dev/null | awk '{if(NR>2)print}' | grep -E ' U | Upgrade| Update' | cut -d '|' -f3 | head -n1 | date -f - +"%s" 2>/dev/null || echo "-1")
130189
fi
131-
# Add check in case this is a brand new built machine that has had
132-
# up to date pacakges installed during build. In this case, neither
133-
# command above will have yielded a value and LAST_UPDATE_TIMESTAMP
134-
# will be empty
135-
136-
if [ "$LAST_UPDATE_TIMESTAMP" == "" ]; then LAST_UPDATE_TIMESTAMP=-1; fi
137190

191+
# Add check in case this is a brand new built machine
192+
if [ "$LAST_UPDATE_TIMESTAMP" = "" ]; then
193+
LAST_UPDATE_TIMESTAMP=-1
194+
fi
138195

139-
echo $BOOT_REQUIRED
140-
echo $UPDATES
141-
echo $SECURITY_UPDATES
142-
echo $LAST_UPDATE_TIMESTAMP
196+
echo "$BOOT_REQUIRED"
197+
echo "$UPDATES"
198+
echo "$SECURITY_UPDATES"
199+
echo "$LAST_UPDATE_TIMESTAMP"
143200

144-
# cache check yum
201+
# cache check yum/dnf
145202
# check if cached check already exists and is nothing but a file
146-
if [ -f $CACHE_YUM_UPDATE ] || [ ! -L $CACHE_YUM_UPDATE ]; then
147-
echo "$YUM_CURRENT" > $CACHE_YUM_UPDATE
203+
if [ -f "$CACHE_YUM_UPDATE" ] || [ ! -L "$CACHE_YUM_UPDATE" ]; then
204+
echo "$YUM_CURRENT" > "$CACHE_YUM_UPDATE"
148205
else
149206
# something is wrong here...
150207
echo "ERROR: invalid check cache file"
151208
exit 2
152209
fi
210+
153211
# cache check results
154-
# check if cached check result already exists and is nothing but a file
155-
if [ -f $CACHE_RESULT_CHECK ] || [ ! -L $CACHE_RESULT_CHECK ]
212+
if [ -f "$CACHE_RESULT_CHECK" ] || [ ! -L "$CACHE_RESULT_CHECK" ]
156213
then
157-
echo $BOOT_REQUIRED > $CACHE_RESULT_CHECK
158-
echo $UPDATES >> $CACHE_RESULT_CHECK
159-
echo $SECURITY_UPDATES >> $CACHE_RESULT_CHECK
160-
echo $LAST_UPDATE_TIMESTAMP >> $CACHE_RESULT_CHECK
214+
echo "$BOOT_REQUIRED" > "$CACHE_RESULT_CHECK"
215+
echo "$UPDATES" >> "$CACHE_RESULT_CHECK"
216+
echo "$SECURITY_UPDATES" >> "$CACHE_RESULT_CHECK"
217+
echo "$LAST_UPDATE_TIMESTAMP" >> "$CACHE_RESULT_CHECK"
161218
else
162219
# something is wrong here...
163220
echo "ERROR: invalid check result cache file"
164221
exit 2
165222
fi
166223
else
167224
# use cache file
168-
cat $CACHE_RESULT_CHECK
225+
cat "$CACHE_RESULT_CHECK"
169226
fi

0 commit comments

Comments
 (0)