-
Notifications
You must be signed in to change notification settings - Fork 105
/
entrypoint.sh
executable file
·427 lines (376 loc) · 12.9 KB
/
entrypoint.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
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
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
#!/bin/bash
# ZoneMinder Dockerfile entrypoint script
# Written by Andrew Bauer <zonexpertconsulting@outlook.com>
#
# This script will start mysql, apache, and zoneminder services.
# It looks in common places for the files & executables it needs
# and thus should be compatible with major Linux distros.
###############
# SUBROUTINES #
###############
# Find ciritical files and perform sanity checks
initialize () {
# check if remote db credentials have been given and set properly
counter=0
for CREDENTIAL in $ZM_DB_HOST $ZM_DB_USER $ZM_DB_PASS $ZM_DB_PASS_FILE $ZM_DB_NAME; do
if [ -n "$CREDENTIAL" ]; then
counter=$((counter+1))
fi
done
# counter = 0 means a local database
# counter = 4 means a remote database
# counter != 0 or 4 means the credentials were not specified correctly and we should fail
remoteDB=0
serverbins="my_print_defaults mysqld_safe"
if [ "$counter" -eq "4" ]; then
echo " * Remote database credentials detected. Continuing..."
remoteDB=1
serverbins=""
elif [ "$counter" -ne "0" ]; then
echo " * Fatal: Remote database credentials not set correctly."
exit 97
fi
# Check to see if this script has access to all the commands it needs
for CMD in cat grep install ln mysql mysqladmin mysqlshow sed sleep su tail usermod head file $serverbins; do
type $CMD &> /dev/null
if [ $? -ne 0 ]; then
echo
echo "ERROR: The script cannot find the required command \"${CMD}\"."
echo
exit 1
fi
done
# Look in common places for the mysqld/MariaDB executable
for FILE in "/usr/sbin/mysqld" "/usr/libexec/mysqld" "/usr/local/sbin/mysqld" "/usr/local/libexec/mysqld"; do
if [ -f $FILE ]; then
MYSQLD=$FILE
break
fi
done
# Look in common places for the apache executable commonly called httpd or apache2
for FILE in "/usr/sbin/httpd" "/usr/sbin/apache2"; do
if [ -f $FILE ]; then
HTTPBIN=$FILE
break
fi
done
# Look in common places for the zoneminder config file - zm.conf
for FILE in "/etc/zm.conf" "/etc/zm/zm.conf" "/usr/local/etc/zm.conf" "/usr/local/etc/zm/zm.conf"; do
if [ -f $FILE ]; then
ZMCONF=$FILE
break
fi
done
# Look in common places for the zoneminder startup perl script - zmpkg.pl
for FILE in "/usr/bin/zmpkg.pl" "/usr/local/bin/zmpkg.pl"; do
if [ -f $FILE ]; then
ZMPKG=$FILE
break
fi
done
# Look in common places for the zoneminder dB update perl script - zmupdate.pl
for FILE in "/usr/bin/zmupdate.pl" "/usr/local/bin/zmupdate.pl"; do
if [ -f $FILE ]; then
ZMUPDATE=$FILE
break
fi
done
# Look in common places for the zoneminder dB creation script - zm_create.sql
for FILE in "/usr/share/zoneminder/db/zm_create.sql" "/usr/local/share/zoneminder/db/zm_create.sql"; do
if [ -f $FILE ]; then
ZMCREATE=$FILE
break
fi
done
# Look in common places for the php.ini relevant to zoneminder
# Search order matters here because debian distros commonly have multiple php.ini's
for FILE in "/etc/php/7.4/apache2/php.ini" "/etc/php/7.2/apache2/php.ini" "/etc/php/7.0/apache2/php.ini" "/etc/php5/apache2/php.ini" "/etc/php.ini" "/usr/local/etc/php.ini"; do
if [ -f $FILE ]; then
PHPINI=$FILE
break
fi
done
# Do we have php-fpm installed
for FILE in "/usr/sbin/php-fpm"; do
if [ -f $FILE ]; then
PHPFPM=$FILE
fi
done
for FILE in $ZMCONF $ZMPKG $ZMUPDATE $ZMCREATE $PHPINI $HTTPBIN $MYSQLD; do
if [ -z $FILE ]; then
echo
echo "FATAL: This script was unable to determine one or more critical files. Cannot continue."
echo
echo "VARIABLE DUMP"
echo "-------------"
echo
echo "Path to zm.conf: ${ZMCONF}"
echo "Path to zmpkg.pl: ${ZMPKG}"
echo "Path to zmupdate.pl: ${ZMUPDATE}"
echo "Path to zm_create.sql: ${ZMCREATE}"
echo "Path to php.ini: ${PHPINI}"
echo "Path to Apache executable: ${HTTPBIN}"
echo "Path to Mysql executable: ${MYSQLD}"
echo
exit 98
fi
done
# Set the php-fpm socket owner
if [ -e /etc/php-fpm.d/www.conf ]; then
mkdir -p /var/run/php-fpm
sed -E 's/^;(listen.(group|owner) = ).*/\1apache/g' /etc/php-fpm.d/www.conf | \
sed -E 's/^(listen\.acl_users.*)/;\1/' > /etc/php-fpm.d/www.conf.n
if [ $? -ne 0 ]; then
echo
echo " * Unable to update php-fpm file"
exit 95
fi
mv -f /etc/php-fpm.d/www.conf.n /etc/php-fpm.d/www.conf
fi
}
# Usage: get_mysql_option SECTION VARNAME DEFAULT
# result is returned in $result
# We use my_print_defaults which prints all options from multiple files,
# with the more specific ones later; hence take the last match.
get_mysql_option (){
result=`my_print_defaults "$1" | sed -n "s/^--$2=//p" | tail -n 1`
if [ -z "$result" ]; then
# not found, use default
result="$3"
fi
}
# Return status of mysql service
mysql_running () {
if [ "$remoteDB" -eq "1" ]; then
mysqladmin ping -u${ZM_DB_USER} -p${ZM_DB_PASS} -h${ZM_DB_HOST} > /dev/null 2>&1
else
mysqladmin ping > /dev/null 2>&1
fi
local result="$?"
if [ "$result" -eq "0" ]; then
echo "1" # mysql is running
else
echo "0" # mysql is not running
fi
}
# Blocks until mysql starts completely or timeout expires
mysql_timer () {
timeout=60
count=0
while [ "$(mysql_running)" -eq "0" ] && [ "$count" -lt "$timeout" ]; do
sleep 1 # Mysql has not started up completely so wait one second then check again
count=$((count+1))
done
if [ "$count" -ge "$timeout" ]; then
echo " * Warning: Mysql startup timer expired!"
fi
}
mysql_datadir_exists() {
if [ -d /var/lib/mysql/mysql ]; then
echo "1" # datadir exists
else
echo "0" # datadir does not exist
fi
}
zm_db_exists() {
if [ "$remoteDB" -eq "1" ]; then
mysqlshow -u${ZM_DB_USER} -p${ZM_DB_PASS} -h${ZM_DB_HOST} ${ZM_DB_NAME} > /dev/null 2>&1
else
mysqlshow zm > /dev/null 2>&1
fi
RETVAL=$?
if [ "$RETVAL" = "0" ]; then
echo "1" # ZoneMinder database exists
else
echo "0" # ZoneMinder database does not exist
fi
}
# The secret sauce to determine wether to use mysql_install_db
# or mysqld --initialize seems to be wether mysql_install_db is a shell
# script or a binary executable
use_mysql_install_db () {
local result="$?"
if [ "$result" -eq "0" ] && [ -n "$MYSQL_INSTALL_DB" ]; then
local contents=$(file -b "$MYSQL_INSTALL_DB")
if [[ "$contents" =~ .*ASCII.text.executable.* ]]; then
echo "1" # mysql_install_db is a shell script
else
echo "0" # mysql_install_db is a binary
fi
else
echo "0" # mysql_install_db does not exist
fi
}
# mysql service management
start_mysql () {
# determine if we are running mariadb or mysql then guess pid location
if [ $(mysql --version |grep -ci mariadb) -ge "1" ]; then
default_pidfile="/var/run/mariadb/mariadb.pid"
else
default_pidfile="/var/run/mysqld/mysqld.pid"
fi
# verify our guessed pid file location is right
get_mysql_option mysqld_safe pid-file $default_pidfile
mypidfile=$result
mypidfolder=${mypidfile%/*}
mysocklockfile=${mypidfolder}/mysqld.sock.lock
if [ "$(mysql_datadir_exists)" -eq "0" ]; then
echo " * First run of MYSQL, initializing DB."
MYSQL_INSTALL_DB=$(type -p mysql_install_db)
if [ "$(use_mysql_install_db)" -eq "1" ]; then
${MYSQL_INSTALL_DB} --user=mysql --datadir=/var/lib/mysql/ > /dev/null 2>&1
else
${MYSQLD} --initialize-insecure --user=mysql --datadir=/var/lib/mysql/ > /dev/null 2>&1
fi
elif [ -e ${mysocklockfile} ]; then
echo " * Removing stale lock file"
rm -f ${mysocklockfile}
fi
# Start mysql only if it is not already running
if [ "$(mysql_running)" -eq "0" ]; then
echo -n " * Starting MySQL database server service"
test -e $mypidfolder || install -m 755 -o mysql -g root -d $mypidfolder
mysqld_safe --user=mysql --timezone="$TZ" > /dev/null 2>&1 &
RETVAL=$?
if [ "$RETVAL" = "0" ]; then
echo " ...done."
mysql_timer # Now wait until mysql finishes its startup
else
echo " ...failed!"
fi
else
echo " * MySQL database server already running."
fi
mysqlpid=`cat "$mypidfile" 2>/dev/null`
}
# Check the status of the remote mysql server using supplied credentials
chk_remote_mysql () {
if [ "$remoteDB" -eq "1" ]; then
echo -n " * Looking for remote database server"
if [ "$(mysql_running)" -eq "1" ]; then
echo " ...found."
else
echo " ...failed!"
return
fi
echo -n " * Looking for existing remote database"
if [ "$(zm_db_exists)" -eq "1" ]; then
echo " ...found."
else
echo " ...not found."
echo -n " * Attempting to create remote database using provided credentials"
mysql -u${ZM_DB_USER} -p${ZM_DB_PASS} -h${ZM_DB_HOST} < $ZMCREATE > /dev/null 2>&1
RETVAL=$?
if [ "$RETVAL" = "0" ]; then
echo " ...done."
else
echo " ...failed!"
echo " * Error: Remote database must be manually configred."
fi
fi
else
# This should never happen
echo " * Error: chk_remote_mysql subroutine called but no sql credentials were given!"
fi
}
# Apache service management
start_http () {
# CentOS/Rocky 8 ships with php-fpm enabled, we need to start it
# Not tested on other distros please provide feedback
if [ -n "$PHPFPM" ]; then
echo -n " * Starting php-fpm web service"
$PHPFPM &> /dev/null
RETVAL=$?
if [ "$RETVAL" -eq "0" ]; then
echo " ...done."
else
echo " ...failed!"
exit 1
fi
fi
echo -n " * Starting Apache http web server service"
# Debian requires we load the contents of envvars before we can start apache
if [ -f /etc/apache2/envvars ]; then
source /etc/apache2/envvars
fi
$HTTPBIN -k start > /dev/null 2>&1
RETVAL=$?
if [ "$RETVAL" = "0" ]; then
echo " ...done."
else
echo " ...failed!"
exit 1
fi
}
# ZoneMinder service management
start_zoneminder () {
echo -n " * Starting ZoneMinder video surveillance recorder"
# Call zmupdate.pl here to upgrade the dB if needed.
# Otherwise zm fails after an upgrade, due to dB mismatch
$ZMUPDATE --nointeractive
$ZMUPDATE --nointeractive -f
$ZMPKG start > /dev/null 2>&1
RETVAL=$?
if [ "$RETVAL" = "0" ]; then
echo " ...done."
else
echo " ...failed!"
exit 1
fi
}
cleanup () {
echo " * SIGTERM received. Cleaning up before exiting..."
kill $mysqlpid > /dev/null 2>&1
$HTTPBIN -k stop > /dev/null 2>&1
sleep 5
exit 0
}
################
# MAIN PROGRAM #
################
echo
initialize
# Set the timezone before we start any services
if [ -z "$TZ" ]; then
TZ="UTC"
fi
echo "date.timezone = $TZ" >> $PHPINI
if [ -L /etc/localtime ]; then
ln -sf "/usr/share/zoneinfo/$TZ" /etc/localtime
fi
if [ -f /etc/timezone ]; then
echo "$TZ" > /etc/timezone
fi
if [ -d "/var/lib/mysql" ]; then
chown -R mysql:mysql /var/lib/mysql/
fi
# Configure then start Mysql
if [ "$remoteDB" -eq "1" ]; then
if [ -n "$ZM_DB_PASS_FILE" ]; then
ZM_DB_PASS=$(cat $ZM_DB_PASS_FILE)
fi
sed -i -e "s/ZM_DB_NAME=.*$/ZM_DB_NAME=$ZM_DB_NAME/g" $ZMCONF
sed -i -e "s/ZM_DB_USER=.*$/ZM_DB_USER=$ZM_DB_USER/g" $ZMCONF
sed -i -e "s/ZM_DB_PASS=.*$/ZM_DB_PASS=$ZM_DB_PASS/g" $ZMCONF
sed -i -e "s/ZM_DB_HOST=.*$/ZM_DB_HOST=$ZM_DB_HOST/g" $ZMCONF
chk_remote_mysql
else
usermod -d /var/lib/mysql/ mysql > /dev/null 2>&1
start_mysql
mysql -u root -e "CREATE USER 'zmuser'@'localhost' IDENTIFIED BY 'zmpass';"
mysql -u root -e "GRANT ALL PRIVILEGES ON *.* TO 'zmuser'@'localhost';"
if [ "$(zm_db_exists)" -eq "0" ]; then
echo " * First run of mysql in the container, creating ZoneMinder dB."
mysql -u root < $ZMCREATE
else
echo " * ZoneMinder dB already exists, skipping table creation."
fi
fi
# Ensure we shutdown our services cleanly when we are told to stop
trap cleanup SIGTERM
# Start Apache
start_http
# Start ZoneMinder
start_zoneminder
# tail logs while running
tail -F /var/log/zoneminder/zm*.log /var/log/zm/zm*.log