-
Notifications
You must be signed in to change notification settings - Fork 3
/
check_softwareupdate.sh
executable file
·198 lines (177 loc) · 5.93 KB
/
check_softwareupdate.sh
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#!/bin/sh
#
# (c)2015 Christian Kujau <[email protected]>
# Nagios check for software updates with various package managers.
#
PATH=/bin:/usr/bin:/sbin:/usr/sbin
RESULT=$(mktemp 2>/dev/null || mktemp -t check_softwareupdate) # MacOS prior to 10.11 needs an argument.
trap "rm -f ${RESULT}" EXIT INT TERM HUP
ERR=3
case $1 in
apk)
sudo apk update > /dev/null || ERR=3
sudo apk upgrade --simulate | awk '/Upgrading/ {print $3}' > "${RESULT}" || ERR=3
grep -Eq "[[:alnum:]]" "${RESULT}" && ERR=1 || ERR=0
;;
cron)
# Not every system will have sudo/doas installed to have the Nagios user check for
# updates, just look at the "opkg" variant below. Let's try to provide a somewhat
# general method to check for updates where we will rely on a cronjob on the system,
# regularly checking for updates and writing in some standardized way to a state
# file. Here, we will only check that state file.
[ -r "$2" ] && STATE="$2" || exit 3
AGE=${3:-2} # State file should be no older than X days (default: 2)
TIMEDIFF=$(( AGE * 60 * 60 * 24 )) # Convert to seconds
T_PACKAGE=$(date -r "${STATE}" +%s)
T_NOW=$(date +%s)
# Check if our package lists are somewhat current.
if [ $(( T_NOW - TIMEDIFF )) -gt "${T_PACKAGE}" ]; then
echo "Statefile ${STATE} is too old!" > "${RESULT}"
ERR=3
else
# The STATE file will be generated by our cronjob of course and
# the output can be controlled by said cronjob. We expect all
# available package upgrades to start with the string "Package".
# Use check_softwareupdate_helper to generate that state file.
grep -E "^Package:" "${STATE}" > "${RESULT}"
grep -Eq "[[:alnum:]]" "${RESULT}" && ERR=1 || ERR=0
fi
;;
dnf)
# FIXME: This check isn't working right now, probably due to:
# > Failed to create session: Bad message for NRPE check
# > https://bugzilla.redhat.com/show_bug.cgi?id=1422381
# echo "ENV" && env && echo "SET" && set && date
#
# This will need the following sudoers(5) rule:
# > nrpe ALL=(ALL) NOPASSWD: /usr/bin/dnf check-update
#
# When using SELinux, we need to set the security context for this script:
# > /sbin/restorecon -v ../check_softwareupdate.sh
#
sudo dnf check-update > "${RESULT}"
case $? in
0)
ERR=0
;;
100)
sed '/^Last metadata expiration/d;/^$/d' -i "${RESULT}"
ERR=1
;;
*)
ERR=3
;;
esac
;;
homebrew)
cd /tmp || exit 3
# This will need the following sudoers(5) rules:
# > nagios ALL=(admin) NOPASSWD:SETENV: /usr/local/bin/brew update
# > nagios ALL=(admin) NOPASSWD:SETENV: /usr/local/bin/brew outdated
sudo -u admin /usr/local/bin/brew update > /dev/null || exit 3
sudo -u admin /usr/local/bin/brew outdated > "${RESULT}"
grep -q "[[:alnum:]]" "${RESULT}" && ERR=1 || ERR=0
;;
macports)
# This will need the following sudoers(5) rule:
# > nagios ALL=(ALL) NOPASSWD: /opt/local/bin/port sync
sudo /opt/local/bin/port sync > /dev/null || exit 3
# We need to set HOME here, because:
#
# > MacPorts provider needs to set HOME while running `port` command.
# > https://projects.puppetlabs.com/issues/13284
# Fixed by:
# > Bug #13284 - missing env vars during provider command execution #606
# > https://github.com/puppetlabs/puppet/pull/606
#
HOME=/var/lib/nagios /opt/local/bin/port echo outdated > "${RESULT}" || exit 3
grep -Eq "[[:alnum:]]" "${RESULT}" && ERR=1 || ERR=0
;;
opkg)
#
# NOTE: currently opkg cannot run as a non-root user w/o some modificatons.
# The best and easiest choice would be to use the "cron" method above.
# However, if we really want to check for upgradable packages as the "nagios"
# user, the following modifications are necessary:
#
# echo 'lock:x:54:nagios' >> /etc/group
# chgrp lock /var/lock/
# chmod g+w /var/lock/
# chgrp -R lock /var/opkg-lists/
# chmod g+ws /var/opkg-lists/
# chmod a+r /etc/opkg/keys/*
#
# See also:
# > Opkg as non-root user?
# > https://forum.openwrt.org/t/opkg-as-non-root-user/64840
#
PLIST=/var/opkg-lists
[ -d ${PLIST} ] || exit 3
AGE=${2:-5} # Package list should be no older than X days (default: 5)
TIMEDIFF=$(( AGE * 60 * 60 * 24 )) # Convert to seconds
T_PACKAGE=$(date -r ${PLIST} +%s)
T_NOW=$(date +%s)
MIN_PKGS=4000 # We expect ~4000 packages.
CNT_PKGS=$(opkg list | wc -l)
# Check if our package lists are somewhat complete.
if [ "${CNT_PKGS}" -lt "${MIN_PKGS}" ]; then
echo "Our package lists may not be complete!" > "${RESULT}"
ERR=3
fi
# Check if our package lists are somewhat current.
if [ $(( T_NOW - TIMEDIFF )) -gt "${T_PACKAGE}" ]; then
echo "Package lists are too old!" > "${RESULT}"
ERR=3
else
opkg list-upgradable > "${RESULT}" || exit 3
sed '/Multiple packages .* providing same name/d' -i "${RESULT}"
grep -Eq "[[:alnum:]]" "${RESULT}" && ERR=1 || ERR=0
fi
;;
osx)
# This will need the following sudoers(5) rule:
# > nagios ALL=(ALL) NOPASSWD: /usr/sbin/softwareupdate -l
sudo softwareupdate -l > "${RESULT}" 2>&1 || exit 3
grep -q "No new software available." "${RESULT}"
ERR=$?
;;
pacman)
sudo pacman --sync --refresh --sysupgrade --print > "${RESULT}" || exit 3
sed -i '/^http/!d' "${RESULT}" || exit 3
grep -Eq '^http' "${RESULT}" && ERR=1 || ERR=0
;;
xbps)
xbps-install --sync --update --dry-run > "${RESULT}" || exit 3
sed -i 's|https://.*||' "${RESULT}" || exit 3
grep -E '^[a-z]' "${RESULT}" && ERR=1 || ERR=0
;;
zypper)
sudo zypper list-updates | awk '/^v/ {printf $5}' > "${RESULT}" || exit 3
grep -Eq "[[:alnum:]]" "${RESULT}" && ERR=1 || ERR=0
;;
*)
echo "Usage: $(basename "$0") [apk|dnf|homebrew|macports|osx|pacman|xbps|zypper]"
echo "Usage: $(basename "$0") [cron] [statefile] [[age]]"
echo "Usage: $(basename "$0") [opkg] [[age]]"
exit 3
;;
esac
# Process the results.
case $ERR in
0)
echo "OK: No software updates available."
exit 0
;;
1)
echo "WARNING: Software update available! $(cat "${RESULT}")"
exit 1
;;
2)
# TODO: what would constitute a CRITICAL status?
exit 2
;;
3)
echo "UNKNOWN: something wicked happened, bailing out. $(cat "${RESULT}")"
exit 3
;;
esac