-
Notifications
You must be signed in to change notification settings - Fork 3
/
conmon
executable file
·139 lines (125 loc) · 3.22 KB
/
conmon
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
#!/bin/sh
#
# NAME
# conmon - Restart service when some criterion fails
#
# SYNOPSIS
# conmon <profile>
#
# DESCRIPTION
# Polls a user-defined `check` command periodically. On failure, the
# user-defined `restart` command is called.
#
# The time between periodic checks is at least `interval` seconds.
# There are some additional delays between the restarts to allow the
# service to act and to prevent frequent but futile restarts during
# extended outages. These timings can be adjusted via the `init_pause`
# and `max_pause` parameters.
#
# The script must be run as root. To reduce the risk of this, `check`
# is executed as `nobody`. This can be configured using the `user`
# parameter.
#
# OPTIONS
# <profile>
# Name of the profile script, corresponding to
# /etc/conmon/<profile>.conf.
#
# EXAMPLE
# A profile that tests Internet connectivity and restarts wlp3s0 on
# failure:
#
# # /etc/conmon/wlp3s0.conf
#
# interval=300 # in seconds
# #user=nobody # user under which `check` is run
# #init_pause=30 # in seconds
# #max_pause=600 # in seconds
#
# check() { # must return 0 on success
# ping -c 5 -W 300 google.com >/dev/null
# }
#
# restart() {
# systemctl restart netctl-auto@wlp3s0
# }
#
# The script itself may be managed via a systemd unit template:
#
# # /etc/systemd/system/[email protected]
#
# [Unit]
# Description=Restart service when some criterion fails
#
# [Service]
# ExecStart=/usr/local/bin/conmon %I
# Restart=always
# RestartSec=600
#
# [Install]
# WantedBy=multi-user.target
#
set -eu
if [ $# -ne 1 ]
then
prog=`basename "$0"`
printf >&2 "usage: %s PROFILE\n" "$prog"
exit 2
fi
interval=600
user=nobody
init_pause=30
max_pause=600
restart() { :; }
profile=$1
. "/etc/conmon/$profile.sh"
pause=$init_pause
# return 37 on immediate failure and 0 on subsequent failures
test_connectivity() {
cd "${TMP:-/tmp}"
if sudo -n -u "$user" profile="$profile" sh <<"EOF"
check() { :; }
. "/etc/conmon/$profile.sh"
exitcode=37
while check
do
if [ "$exitcode" -eq 1 ]
then echo "Connection active."
fi
exitcode=0
sleep "$interval"
done
echo "Connection failed."
exit "$exitcode"
EOF
then return 0
else return "$?"
fi
}
# allow some time for service to initialize
# since it may have been started in parallel
sleep "$pause"
while :
do
# wait for failures; if it didn't fail immediately, reset the pause timer
if test_connectivity
then pause=$init_pause
else
exitcode=$?
if [ "$exitcode" -ne 37 ]
then exit "$exitcode"
fi
fi
# restart and then pause for some time
echo "Restarting ..."
restart && :
e=$?
[ $e -eq 0 ] || printf >&2 "Warning: restart exited with %i.\n" $e
echo Restarted.
sleep "$pause"
# double the pause timer, up to some maximum
pause=`expr "$pause" \* 2`
if [ "$pause" -gt "$max_pause" ]
then pause=$max_pause
fi
done