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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
|
#!/bin/bash
#set -x
# License: The BSD 3-Clause License
#
# Copyright (c) 2014, Johan Ryberg
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# check_reboot-required
# Plugin for NRPE (Nagios Remote Plugin Executor) for
# Debian/Ubuntu/RedHat/CentOS to check if a reboot are required and
# also list packages that requires reboot
# Web: https://github.com/jryberg/nagios-plugins/
APPNAME=`basename $0`
VERSION="1.0"
# Defining standard messages and exit error levels
# https://nagios-plugins.org/doc/guidelines.html
OK_EXIT_CODE=0
WARNING_EXIT_CODE=1
CRITICAL_EXIT_CODE=2
UNKNOWN_EXIT_CODE=3
OK_MSG="OK"
WARNING_MSG="Warning"
CRITICAL_MSG="Critical"
UNKNOWN_MSG="Unknown"
# Using Unknown as default
EXIT_CODE=$UNKNOWN_EXIT_CODE
EXIT_MSG=$UNKNOWN_MSG
# Stupid warning and critical levels, this cannot be determined by numbers
# some may want to have this anyway. Default will be a warning if a reboot
# are required and never critical
# -1 = disable service status
WARNING_LEVEL=1
CRITICAL_LEVEL=-1
# Path to reboot-required
REBOOT_REQUIRED_PATH="/var/run/reboot-required"
REBOOT_REQUIRED_PKGS_PATH="/var/run/reboot-required.pkgs"
# Function to explain how to use the program
function_usage () {
cat - <<EOF
Usage: ${appname} [--help]
Usage: ${appname} -d status [-w warn] [-c crit]
This check command checks if a reboot are required after an upgrade. It will
also list packages that requires a reboot to ease the decision for the
sysadmin if/when a reboot needs to be carried out.
WARNING: It's impossible by numbers to decide if a reboot are required by
raising a "warning" or "critical" event. A patch for 0-day vulnerability
will probably required immediate attention and less important updates can
wait until next scheduled maintenance window. Please read documentation
for each update.
Default without any options will be Warning for 1 or more packages
that requires reboot. Critical event will not be raised.
--help
Show this help
-V, --version
Show version
-s
Default service status when reboot are needed but package information
are missing. w=Warning, c=Critical
-w
Warning: Number of packages needing reboot as integer. Default: 1
-c
Critical: Number of packages needing reboot as integer. Disabled as default
Example:
${APPNAME} -s w
EOF
}
function distro_name() {
if [[ -e /etc/redhat-release ]]; then
REDHAT_RELEASE=`cat /etc/redhat-release`
if [[ `cat /etc/redhat-release | grep CentOS` != "" ]]; then
echo "CentOS"
elif [[ `cat /etc/redhat-release | grep "Red Hat"` != "" ]]; then
echo "Red Hat"
else
echo "$REDHAT_RELEASE"
fi
elif [[ -e /etc/lsb-release ]]; then
. /etc/lsb-release
echo $DISTRIB_ID
elif [[ -e /etc/debian_version ]]; then
DEBIAN_VER=`cat /etc/debian_version`
echo "Debian"
else
echo "OS not recognized"
fi
}
function CheckDebianRebootRequired() {
if [ ! -f ${REBOOT_REQUIRED_PATH} ]; then
# Reboot not required
EXIT_MSG=$OK_MSG
EXIT_MSG_BODY="No reboot required|Packages=0;${WARNING_LEVEL//-1/};${CRITICAL_LEVEL//-1/};0"
EXIT_MSG_NR_PACKAGES=0
EXIT_CODE=$OK_EXIT_CODE
else
# Reboot required
NR_OF_PACKAGES=0
if [ -f ${REBOOT_REQUIRED_PKGS_PATH} ]; then
NR_OF_PACKAGES=`wc -l ${REBOOT_REQUIRED_PKGS_PATH} | awk '{ print $1 }'`
fi
if [ ${NR_OF_PACKAGES} -gt 0 ]; then
if [ ${NR_OF_PACKAGES} -ge ${CRITICAL_LEVEL} ] && [ ${CRITICAL_LEVEL} -ne "-1" ];then
EXIT_MSG=$CRITICAL_MSG
EXIT_CODE=$CRITICAL_EXIT_CODE
elif [ ${NR_OF_PACKAGES} -ge ${WARNING_LEVEL} ] && [ ${WARNING_LEVEL} -ne "-1" ];then
EXIT_MSG=$WARNING_MSG
EXIT_CODE=$WARNING_EXIT_CODE
else
EXIT_MSG=$OK_MSG
EXIT_CODE=$OK_EXIT_CODE
fi
EXIT_MSG_BODY="`cat ${REBOOT_REQUIRED_PATH}`<br/>Packages:<br/>`cat ${REBOOT_REQUIRED_PKGS_PATH} | sed ':a;N;$!ba;s/\n/<br\/>/g'`|Packages=${NR_OF_PACKAGES};${WARNING_LEVEL//-1/};${CRITICAL_LEVEL//-1/};0"
else
if [[ ${STATUS} = "w" ]]; then
EXIT_MSG=$WARNING_MSG
EXIT_CODE=$WARNING_EXIT_CODE
else
EXIT_MSG=$CRITICAL_MSG
EXIT_CODE=$CRITICAL_EXIT_CODE
fi
EXIT_MSG_BODY="`cat ${REBOOT_REQUIRED_PATH}`|Packages=U;${WARNING_LEVEL//-1/};${CRITICAL_LEVEL//-1/};0"
fi
fi
}
function CheckRedHatRebootRequired() {
LAST_KERNEL=`/bin/rpm -q --last kernel | /usr/bin/head -1 | /usr/bin/perl -pe 's/^kernel-(\S+).*/$1/'`
RUNNING_KERNEL=`uname -r`
if [[ $LAST_KERNEL != $RUNNING_KERNEL ]]; then
EXIT_MSG=$CRITICAL_MSG
EXIT_MSG_BODY="Reboot required, the running kernel ($RUNNING_KERNEL) is different from the last kernel installed ($LAST_KERNEL)."
EXIT_MSG_NR_PACKAGES=1
EXIT_CODE=$CRITICAL_EXIT_CODE
else
EXIT_MSG=$OK_MSG
EXIT_MSG_BODY="No reboot required|Packages=0;${WARNING_LEVEL//-1/};${CRITICAL_LEVEL//-1/};0"
EXIT_MSG_NR_PACKAGES=0
EXIT_CODE=$OK_EXIT_CODE
fi
}
# Process arguments
while [ $# -gt 0 ]; do
OPT="$1"
case "${OPT}" in
--help)
function_usage
exit $OK_EXIT_CODE
;;
-s)
shift
case $1 in
w|c)
STATUS="${1}"
;;
*)
echo "${APPNAME}: Service status must be w (Warning) or c (Critical)"
exit $UNKNOWN_EXIT_CODE
;;
esac
shift
;;
-w)
shift
if [[ ${1} =~ ^[0-9]+$ ]]; then
WARNING_LEVEL="${1}"
else
echo "${APPNAME}: Warning level must be positive integer"
exit $UNKNOWN_EXIT_CODE
fi
shift
;;
-c)
shift
if [[ ${1} =~ ^[0-9]+$ ]]; then
CRITICAL_LEVEL="${1}"
else
echo "${APPNAME}: Critical level must be positive integer"
exit $UNKNOWN_EXIT_CODE
fi
shift
;;
--version|-V)
echo "${APPNAME} ${VERSION}"
exit $OK_EXIT_CODE
;;
*)
echo "${APPNAME}: invalid option '${1}'"
echo "Try '${APPNAME} --help' for more information."
exit $UNKNOWN_EXIT_CODE
;;
esac
done
if [ -z ${STATUS} ]; then
echo "${APPNAME}: -s Status argument are missing"
exit $UNKNOWN_EXIT_CODE
fi
case `distro_name` in
"OS not recognized")
echo "OS wasn't recognized, please report to maintainer of this script."
exit $UNKNOWN_EXIT_CODE
;;
"Debian"|"Ubuntu")
CheckDebianRebootRequired
;;
"Red Hat"|"CentOS")
CheckRedHatRebootRequired
;;
*)
echo "OS wasn't recognized, please report to maintainer of this script."
exit $UNKNOWN_EXIT_CODE
;;
esac
# Echo message and exit
echo "${EXIT_MSG}: ${EXIT_MSG_BODY}"
exit $EXIT_CODE
|