@@ -14,7 +14,9 @@ readonly REBOOT_HINT_PATH=${REBOOT_HINT_PATH:-/run/smart-restart}
14
14
readonly REBOOT_HINT_MARKER=" ${REBOOT_HINT_PATH} " /reboot-hint-marker
15
15
readonly CONF_PATH=${CONF_PATH:-/ etc/ smart-restart-conf.d}
16
16
readonly DENYLISTS=(" ${CONF_PATH} " /* -denylist)
17
+ # shellcheck disable=SC2207
17
18
readonly PRE_RESTART=($( ls " $CONF_PATH " /* pre-restart | sort -n) )
19
+ # shellcheck disable=SC2207
18
20
readonly POST_RESTART=($( ls " $CONF_PATH " /* post-restart | sort -n) )
19
21
20
22
SYSCTL_COMMAND=" ${SYSCTL_COMMAND:- systemctl} "
@@ -25,14 +27,26 @@ DEBUG=${DEBUG:-}
25
27
26
28
SERVICES=()
27
29
BLOCKED_SERVICES=()
30
+ PRE_RESTART_HEALTHY=0
31
+ POST_RESTART_HEALTHY=0
28
32
29
33
INF () { echo " $1 " ; }
30
34
DBG () { [[ " $DEBUG " != " " ]] && >&2 echo " $1 " ; }
31
35
CRIT () { >&2 echo " *** ERROR: $1 " ; }
32
36
37
+ assert_root () {
38
+ if [[ " $( id -u) " != " 0" ]]; then
39
+ CRIT " Please run this script as root."
40
+ exit 1
41
+ fi
42
+ return 0
43
+ }
44
+
33
45
assemble_service_list () {
46
+ # shellcheck disable=SC2207
34
47
local all_services=($( $NEEDS_RESTARTING_COMMAND -s | xargs) )
35
48
49
+ # shellcheck disable=SC2048
36
50
BLOCKED_SERVICES=(" $( sed " s/#.*//g" ${DENYLISTS[*]} ) " )
37
51
38
52
DBG " Denylist: ${DENYLISTS[*]} "
@@ -60,14 +74,16 @@ execute_pre_hooks() {
60
74
restart_services () {
61
75
local -i retval=0
62
76
63
- if [[ ${# SERVICES[@]} != 0 ]]; then
77
+ # shellcheck disable=SC2086
78
+ if [[ ${# SERVICES[@]} != 0 ]]; then
64
79
DBG " Attempting to restart services: ${SERVICES[*]} "
65
- # shellcheck disable=SC2048
80
+ # shellcheck disable=SC2048,SC2086
66
81
$SYSCTL_COMMAND restart ${SERVICES[*]} || retval=$?
67
82
else
68
83
DBG " No services to restart"
69
84
fi
70
-
85
+
86
+
71
87
if [[ ! " ${BLOCKED_SERVICES[*]} " =~ " systemd" ]]; then
72
88
DBG " Attempting to restart systemd itself"
73
89
$SYSCTL_COMMAND daemon-reexec || retval=$?
@@ -77,6 +93,42 @@ restart_services() {
77
93
return $retval
78
94
}
79
95
96
+ # Though, {pre,post} health checks could live in restart_services(), I've moved them outside to be able to test the functionality.
97
+ count_pre_restart_health () {
98
+ DBG " No of services to check (pre-restart): ${# SERVICES[@]} "
99
+ if [[ ${# SERVICES[@]} != 0 ]]; then
100
+ # shellcheck disable=SC2048,SC2086
101
+ PRE_RESTART_HEALTHY=$( $SYSCTL_COMMAND status ${SERVICES[*]} | grep " Active" | grep -cE " active \(running\)" )
102
+ fi
103
+ }
104
+
105
+ count_post_restart_health () {
106
+ DBG " No of services to check (post-restart): ${# SERVICES[@]} "
107
+
108
+ if [[ ${# SERVICES[@]} != 0 ]]; then
109
+ # shellcheck disable=SC2048,SC2086
110
+ POST_RESTART_HEALTHY=$( $SYSCTL_COMMAND status ${SERVICES[*]} | grep " Active" | grep -cE " active \(running\)" )
111
+ fi
112
+ DBG " Pre restart cnt: $PRE_RESTART_HEALTHY "
113
+ DBG " Post restart cnt: $POST_RESTART_HEALTHY "
114
+
115
+ if [[ " $PRE_RESTART_HEALTHY " != " $POST_RESTART_HEALTHY " ]]; then
116
+ S=()
117
+ for SERVICE in " ${SERVICES[@]} " ; do
118
+ $SYSCTL_COMMAND is-active ${SERVICE}
119
+ local -i retval=$?
120
+
121
+ if [[ $retval -gt 0 ]]; then
122
+ S+=(" ${SERVICE} " )
123
+ fi
124
+ done
125
+
126
+ CRIT " Not all services could be successfully started. Failed services: ${S[*]} "
127
+
128
+ return 1
129
+ fi
130
+ }
131
+
80
132
execute_post_hooks () {
81
133
DBG " Executing post-restart hooks: ${POST_RESTART[*]} "
82
134
for HOOK in " ${POST_RESTART[@]} " ; do
@@ -90,12 +142,14 @@ execute_post_hooks() {
90
142
# This means, we need to consolidate a few information sources here to be sure.
91
143
# 1) Check if processess actually got restarted (and ignore the "denylisted" services)
92
144
# 2) Remove userspace components from the reboot-hint output
93
- readonly OS_VERSION=$( cut -d " :" -f6 /etc/system-release-cpe)
145
+ # shellcheck disable=SC2155
146
+ LOCAL_OS_VERSION=$( cut -d " :" -f6 /etc/system-release-cpe)
147
+ OS_VERSION=${OS_VERSION:- $LOCAL_OS_VERSION }
94
148
95
149
generate_reboot_hint_marker () {
96
150
local -i reboot_hint=0
97
151
local -i retval=0
98
-
152
+ # shellcheck disable=SC2155
99
153
local post_restart_services=$( $NEEDS_RESTARTING_COMMAND -s | xargs)
100
154
local failed_services=()
101
155
for SERVICE in $post_restart_services ; do
@@ -106,6 +160,8 @@ generate_reboot_hint_marker() {
106
160
fi
107
161
done
108
162
163
+ count_post_restart_health || retval=$?
164
+
109
165
local reboothint_separator=" "
110
166
111
167
# Consistency is key, that's why the output of needs-restarting --reboothint has different styles for yum & dnf (output for glibc):
@@ -117,11 +173,12 @@ generate_reboot_hint_marker() {
117
173
reboothint_separator=" *"
118
174
else
119
175
CRIT " ERROR: Could not determine OS. I won't create a reboot hint marker"
120
- exit 1
176
+ return 1
121
177
fi
122
178
123
179
# Those are the packages `needs-restarting` is scanning for. We're going to ignore the one's we know we can't restart
124
180
# ['kernel', 'kernel-rt', 'glibc', 'linux-firmware', 'systemd', 'udev', 'openssl-libs', 'gnutls', 'dbus']
181
+ # shellcheck disable=SC2155
125
182
local updated_components=$( $NEEDS_RESTARTING_COMMAND --reboothint | grep -v " glibc\|systemd\|openssl-libs\|gnutls\|dbus\|udev" | grep -- " ${reboothint_separator} " )
126
183
# At this point $updated_components should only report in case kernel* or linux-* was updated.
127
184
@@ -130,6 +187,19 @@ generate_reboot_hint_marker() {
130
187
DBG " Encountered updates we cannot restart without a reboot: $updated_components "
131
188
fi
132
189
190
+ if [[ " $PRE_RESTART_HEALTHY " != " $POST_RESTART_HEALTHY " ]]; then
191
+ reboot_hint=1
192
+ # shellcheck disable=SC2048
193
+ for SERVICE in ${SERVICES[*]} ; do
194
+ $SYSCTL_COMMAND status " $SERVICE "
195
+
196
+ if [[ $? != 0 ]]; then
197
+
198
+ CRIT " Service \" ${SERVICE} \" failed to start again."
199
+ fi
200
+ done
201
+ fi
202
+
133
203
134
204
if [[ $reboot_hint == 1 ]]; then
135
205
mkdir -p " $REBOOT_HINT_PATH "
@@ -144,9 +214,11 @@ generate_reboot_hint_marker() {
144
214
}
145
215
146
216
if [[ -z " $IS_TESTING " ]]; then
217
+ assert_root
147
218
assemble_service_list
219
+ count_pre_restart_health
148
220
execute_pre_hooks
149
221
restart_services
150
222
execute_post_hooks
151
- generate_reboot_hint_marker
152
- fi
223
+ generate_reboot_hint_marker || exit $?
224
+ fi
0 commit comments