-
Notifications
You must be signed in to change notification settings - Fork 25
/
install.sh
841 lines (711 loc) · 23.6 KB
/
install.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
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
#!/bin/bash
#
# That is installation script for storage system monitoring by FASTVPS Eesti OU
# If you have any questions about that system, please contact us:
# - https://github.com/FastVPSEestiOu/storage-system-monitoring
# - https://bill2fast.com (via ticket system)
set -u
# Disable interactive mode when configuring packages
export DEBIAN_FRONTEND='noninteractive'
# Setting text colors
TXT_GRN='\e[0;32m'
TXT_RED='\e[0;31m'
TXT_YLW='\e[0;33m'
TXT_RST='\e[0m'
# Set variable for pid
PID=$$
# Path for binaries
BIN_PATH='/usr/local/bin'
# Path of our repo, used for downloads
REPO_PATH='https://raw.githubusercontent.com/FastVPSEestiOu/storage-system-monitoring/master'
# Name of our script
SCRIPT_NAME='storage_system_fastvps_monitoring.pl'
# Path of our cron task
CRON_FILE='/etc/cron.d/storage-system-monitoring-fastvps'
# Static header for our cron task
CRON_HEADER='# FastVPS disk monitoring tool
# https://github.com/FastVPSEestiOu/storage-system-monitoring
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
# Suffix we add to moved smartd.conf
SMARTD_SUFFIX="fastvps_backup.${PID}"
# Static header for our smartd.conf
SMARTD_HEADER="# smartd.conf by FastVPS
# backup version of distrib file saved to /etc/smartd.conf.$SMARTD_SUFFIX
# Discover disks and run short tests every day at 02:00 and long tests every sunday at 03:00"
# Stable smartctl version (SVN revision)
SMARTCTL_STABLE_VERSION='7.2'
SMARTCTL_STABLE_REVISION='5155'
# Smartd config path
declare -A SMARTD_CONF_FILE
SMARTD_CONF_FILE["deb"]='/etc/smartd.conf'
SMARTD_CONF_FILE["deb_old"]='/etc/smartd.conf'
SMARTD_CONF_FILE["rpm_old"]='/etc/smartd.conf'
SMARTD_CONF_FILE["rpm_new"]='/etc/smartmontools/smartd.conf'
OS=''
ARCH=''
OS_TYPE=''
CRON_MINUTES=''
RAID_TYPE=''
# Dependencies
declare -A PKG_DEPS
PKG_DEPS["deb"]='wget libstdc++5 smartmontools liblwp-useragent-determined-perl libnet-https-any-perl libcrypt-ssleay-perl libjson-perl'
PKG_DEPS["deb_old"]='wget libstdc++5 smartmontools liblwp-useragent-determined-perl libnet-https-any-perl libcrypt-ssleay-perl libjson-perl'
PKG_DEPS["rpm_old"]='wget libstdc++ smartmontools perl-Crypt-SSLeay perl-libwww-perl perl-JSON'
PKG_DEPS["rpm_new"]='wget libstdc++ smartmontools perl-libwww-perl perl-JSON perl-LWP-Protocol-https'
declare -A PKG_INSTALL
PKG_INSTALL["deb"]='apt-get update -qq && apt-get install -qq'
PKG_INSTALL["deb_old"]='apt-get update -o Acquire::Check-Valid-Until=false -qq && apt-get install -qq --allow-unauthenticated'
PKG_INSTALL["rpm_old"]='yum install -q -y'
PKG_INSTALL["rpm_new"]='yum install -q -y'
# List of packages which we do NOT want to update, in form of regex
declare -A PKG_UNSAFE
PKG_UNSAFE["deb"]='Inst libc6|Inst apache2|Inst php'
PKG_UNSAFE["deb_old"]='Inst libc6|Inst apache2|Inst php'
PKG_UNSAFE["rpm_old"]='^ glibc|^ httpd|^ php'
PKG_UNSAFE["rpm_new"]='^ glibc|^ httpd|^ php'
# And command for it
declare -A PKG_INSTALL_TEST
PKG_INSTALL_TEST["deb"]='apt-get update && apt-get install -s'
PKG_INSTALL_TEST["deb_old"]='apt-get update -o Acquire::Check-Valid-Until=false -qq && apt-get install -s'
PKG_INSTALL_TEST["rpm_old"]='yum install --assumeno'
PKG_INSTALL_TEST["rpm_new"]='yum install --assumeno'
# Some fancy echoing
_echo_OK()
{
echo -e " -> ${TXT_GRN}OK${TXT_RST}"
}
_echo_FAIL()
{
echo -e " -> ${TXT_RED}FAIL${TXT_RST}"
}
_echo_tabbed()
{
local message=$1
echo -e " -> $message"
}
_echo_result()
{
local result=$*
if [[ "$result" -eq 0 ]]; then
_echo_OK
else
_echo_FAIL
exit 1
fi
}
# Detect OS
_detect_os()
{
local issue_file='/etc/issue'
local os_release_file='/etc/os-release'
local redhat_release_file='/etc/redhat-release'
local os=''
local name=''
local version=''
# First of all, trying os-relese file
if [ -f $os_release_file ]; then
name=$(grep '^NAME=' $os_release_file | awk -F'[" ]' '{print $2}')
version=$(grep '^VERSION_ID=' $os_release_file | awk -F'[". ]' '{print $2}')
os="${name}${version}"
else
# If not, trying redhat-release file (mainly because of bitrix-env)
if [ -f $redhat_release_file ]; then
os=$(head -1 /etc/redhat-release | sed -re 's/([A-Za-z]+)[^0-9]*([0-9]+).*$/\1\2/')
else
# Else, trying issue file
if [ -f $issue_file ]; then
os=$(head -1 $issue_file | sed -re 's/([A-Za-z]+)[^0-9]*([0-9]+).*$/\1\2/')
else
# If none of that files worked, exit
echo -e "${TXT_RED}Cannot detect OS. Exiting now"'!'"${TXT_RST}"
exit 1
fi
fi
fi
OS=$os
}
# Detect architecture
_detect_arch()
{
local arch=''
local uname=''
uname=$(uname -m)
if [[ $uname == 'x86_64' ]]; then
arch=64
else
arch=32
fi
ARCH=$arch
}
# Select OS type based on OS
_select_os_type()
{
local os=$1
local os_type=''
case $os in
Debian[6-7] )
os_type='deb_old'
;;
Debian[8-9]|Debian1[0-2]|Ubuntu* )
os_type='deb'
;;
CentOS6 )
os_type='rpm_old'
;;
CentOS[7-8]|AlmaLinux[8-9]|Rocky[8-9] )
os_type='rpm_new'
;;
* )
echo "We can do nothing on $os. Exiting."
_echo_FAIL
exit 1
;;
esac
OS_TYPE=$os_type
}
# Check and install needed software
_install_deps()
{
local os_type=$1
local pkgs_to_install=()
local unsafe_pkgs=()
# Check if we have packages needed
local pkg=''
local result=''
for pkg in ${PKG_DEPS[$os_type]}; do
if ! _check_pkg "$os_type" "$pkg" ; then
pkgs_to_install+=("$pkg")
fi
done
if [[ ${#pkgs_to_install[@]} -eq 0 ]]; then
_echo_tabbed "We have everything we need."
return 0
else
_echo_tabbed "Installing: ${TXT_YLW}${pkgs_to_install[*]}${TXT_RST} ..."
# Check if we are going to break something
mapfile -t < <( eval "${PKG_INSTALL_TEST[$os_type]}" "${pkgs_to_install[@]}" ) result
for (( i=0; i<${#result[@]}; i++ )); do
if [[ "${result[i]}" =~ ${PKG_UNSAFE[$os_type]} ]]; then
unsafe_pkgs+=("${result[i]}")
fi
done
if [[ ${#unsafe_pkgs[@]} -gt 0 ]]; then
echo "We are going to update something we do not want to:"
for (( i=0; i<${#unsafe_pkgs[@]}; i++ )); do
echo "${unsafe_pkgs[i]}";
done
echo -e "\nYou can check it yourself with command:\n${PKG_INSTALL_TEST[$os_type]}" "${pkgs_to_install[@]}"
return 1
fi
# Catch error in variable
if IFS=$'\n' result=( $(eval "${PKG_INSTALL[$os_type]}" "${pkgs_to_install[@]}" 2>&1) ); then
return 0
# And output it, if we had nonzero exit code
else
echo
for (( i=0; i<${#result[@]}; i++ )); do
echo "${result[i]}";
done
return 1
fi
fi
}
# Check package
_check_pkg()
{
local os_type=$1
local pkg=$2
case $os_type in
deb* )
if dpkg-query -W -f='\${Status}' "$pkg" 2>&1 | grep -qE '^(\$install ok installed)+$'; then
return 0
else
return 1
fi
;;
rpm* )
if rpm --quiet -q "$pkg"; then
return 0
else
return 1
fi
;;
* )
_echo_tabbed "We can do nothing on $os_type. Exiting."
exit 1
;;
esac
}
# Function to download with check
_dl_and_check()
{
local remote_path=$1
local local_path=$2
local os=$OS
local result=()
local wget_param=()
# Adding --no-check-certificate on old OS
case $os in
Debian6 )
wget_param=(--no-check-certificate --verbose)
;;
* )
wget_param=(--verbose)
;;
esac
# Clean target path before download
if [[ -x "$local_path" ]]; then
rm -f "$local_path";
fi
# Catch error in variable
if IFS=$'\n' result=( $(wget "${wget_param[@]}" "$remote_path" --output-document="$local_path" 2>&1) ); then
return 0
# And output it, if we had nonzero exit code
else
echo
for (( i=0; i<${#result[@]}; i++ )); do
echo "${result[i]}";
done
return 1
fi
}
# Install RAID tools if needed
_install_raid_tools()
{
local bin_path=$1
local repo_path=$2
local arch=$3
local util_path=''
local dl_path=''
local raid_type=''
# Detect RAID
local sys_block_check=''
sys_block_check=$(cat /sys/block/*/device/vendor /sys/block/*/device/model 2>/dev/null | grep -oEm1 'Adaptec|LSI|PERC|ASR8405')
# Select utility to install
case $sys_block_check in
# arcconf for Adaptec
ASR8405 )
raid_type='adaptec'
util_path="${bin_path}/arcconf"
_echo_tabbed "Found RAID: ${TXT_YLW}${sys_block_check}${TXT_RST}"
dl_path="${repo_path}/raid_monitoring_tools/arcconf_v2"
;;
Adaptec )
raid_type='adaptec'
util_path="${bin_path}/arcconf"
local adaptec_version=''
adaptec_version=$(lspci -m | awk -F\" '/Adaptec/ {print $(NF-1)}')
_echo_tabbed "Found RAID: ${TXT_YLW}${sys_block_check} ${adaptec_version}${TXT_RST}"
# Select arcconf version dpending on controller version
case $adaptec_version in
# Old Adaptec controller (2xxx-5xxx) - Adaptec Storage Manager v7
*[2-5][0-9][0-9][0-9] )
dl_path="${repo_path}/raid_monitoring_tools/arcconf${arch}_old"
;;
# Newer Adaptec controller (6xxx-8xxx) - arcconf v2
*[6-8][0-9][0-9][0-9] )
dl_path="${repo_path}/raid_monitoring_tools/arcconf_v2"
;;
# Even newer Adaptec controller (SmartRAID 31xx) - arcconf v3
*SmartRAID*31[0-9][0-9]* )
dl_path="${repo_path}/raid_monitoring_tools/arcconf_v3"
;;
# Otherwise exit
* )
echo "We don't know, what arcconf version is needed."
return 1
;;
esac
;;
# megacli for LSI (PERC is LSI controller on DELL)
LSI|PERC )
raid_type='lsi'
_echo_tabbed "Found RAID: ${TXT_YLW}${sys_block_check}${TXT_RST}"
util_path="${bin_path}/megacli"
dl_path="${repo_path}/raid_monitoring_tools/megacli${arch}"
;;
# Nothing if none RAID found
'' )
raid_type='soft'
_echo_tabbed "No HW RAID."
;;
# Fallback that should never be reached
* )
_echo_tabbed "Unknown RAID type: ${TXT_YLW}${sys_block_check}${TXT_RST}. Exiting."
return 1
;;
esac
# Set raid type for smartd
RAID_TYPE="$raid_type"
# Download selected utility
case $raid_type in
soft )
return 0
;;
adaptec|lsi )
if _dl_and_check "$dl_path" "$util_path"; then
chmod +x "$util_path"
_echo_tabbed "Installed ${TXT_YLW}${util_path}${TXT_RST}"
RAID_TYPE="$raid_type"
return 0
else
return 1
fi
;;
# Fallback that should never be reached
* )
_echo_tabbed "Unknown RAID type: ${TXT_YLW}${raid_type}${TXT_RST}. Exiting."
return 1
;;
esac
}
# Install new smartctl binary, if we have too old one
_install_smartctl()
{
local bin_path=$1
local repo_path=$2
local arch=$3
local smartctl_stable_version=$4
local smartctl_stable_revision=$5
local smartctl_current_version=''
local smartctl_current_revision=''
local version_comp_result=''
local util_path="${bin_path}/smartctl"
local dl_path="${repo_path}/raid_monitoring_tools/smartctl${arch}"
smartctl_current_version=$(smartctl --version | awk '/^smartmontools release/ {print $3}')
smartctl_current_revision=$(smartctl --version | awk '/^smartmontools SVN rev/ {print $4}')
# If current version is lower then stable, download a new one
# We'll get exit code 2 if current version is lower than stable version
_version_copmare "$smartctl_current_version" "$smartctl_stable_version"
version_comp_result=$?
if [[ "$version_comp_result" -eq "2" ]] || [[ "$smartctl_current_revision" -lt "$smartctl_stable_revision" ]]; then
if _dl_and_check "$dl_path" "$util_path"; then
chmod +x "$util_path"
_echo_tabbed "Installed ${TXT_YLW}${util_path}${TXT_RST}"
return 0
else
return 1
fi
else
_echo_tabbed "We have smartctl version ${TXT_YLW}${smartctl_current_version}${TXT_RST} (rev. ${TXT_YLW}${smartctl_current_revision}${TXT_RST}) here."
return 0
fi
}
# Function to compare dotted versions
_version_copmare()
{
# Compares two versions
# Returns:
# 0 -> first = second
# 1 -> first > second
# 2 -> first < second
local first_string=$1
local second_string=$2
local first_array=()
local second_array=()
# Split versions into arrays
IFS='.' read -ra first_array <<< "$first_string"
IFS='.' read -ra second_array <<< "$second_string"
# Fill empty fields in first array with zeros
for ((i=${#first_array[@]}; i<${#second_array[@]}; i++)); do
first_array[$i]=0
done
for ((i=0; i<${#first_array[@]}; i++)); do
# Fill empty fields in second array with zeros
if [[ -z ${second_array[$i]} ]]; then
second_array[$i]=0
fi
# "10#" forces decimal numbers interpretation
if ((10#${first_array[$i]} > 10#${second_array[$i]})); then
return 1
fi
if ((10#${first_array[$i]} < 10#${second_array[$i]})); then
return 2
fi
done
return 0
}
# Install monitoring script
_install_script()
{
local bin_path=$1
local repo_path=$2
local script_name=$3
local cron_file=$4
local cron_minutes=$5
local cron_header=$6
local script_local="${bin_path}/${script_name}"
local script_remote="${repo_path}/${script_name}"
if _dl_and_check "$script_remote" "$script_local"; then
chmod +x -- "$script_local"
_echo_tabbed "Installed ${TXT_YLW}${script_local}${TXT_RST}"
else
return 1
fi
if _set_cron "$cron_file" "$script_local" "$cron_minutes" "$cron_header"; then
_echo_tabbed "Installed ${TXT_YLW}${cron_file}${TXT_RST}"
return 0
else
return 1
fi
}
# Add cron task for script
_set_cron()
{
local cron_file=$1
local script_local=$2
local cron_minutes=$3
local cron_header=$4
local cron_text=''
local cron_line="$cron_minutes * * * * root $script_local --cron >/dev/null 2>&1"
read -r -d '' cron_text <<EOF
$cron_header
$cron_line
EOF
echo "$cron_text" > "$cron_file"
chmod 644 -- "$cron_file"
}
# Detect NVMe (for smartd config)
_detect_nvme()
{
if [[ -b /dev/nvme0n1 ]]; then
return 0;
else
return 1;
fi
}
# Configure SMARTD
_set_smartd()
{
local raid_type=$1
local smartd_header=$2
local os_type=$3
local smartd_suffix=$4
local smartd_conf_file=${SMARTD_CONF_FILE[$os_type]}
local smartd_conf_backup=${smartd_conf_file}.${smartd_suffix}
local smartd_conf=''
local drive=''
local drives=()
local lines=()
# Select smartd.conf for our RAID type
case $raid_type in
soft )
if _detect_nvme; then
lines+=('DEVICESCAN -d nvme -d removable -n standby -s (S/../.././02|L/../../7/03)')
else
lines+=('DEVICESCAN -d removable -n standby -s (S/../.././02|L/../../7/03)')
fi
;;
adaptec )
# For older controllers (aacraid)
if [[ -d '/sys/bus/pci/drivers/aacraid' ]]; then
# Try to load sg module if it is not loaded for some reason
if [[ ! -c /dev/sg0 ]]; then
# Catch error in variable
if IFS=$'\n' result=( $(modprobe sg 2>&1) ); then
_echo_tabbed "Loaded ${TXT_YLW}sg${TXT_RST} module."
# And output it, if we had nonzero exit code
else
echo
for (( i=0; i<${#result[@]}; i++ )); do
echo "${result[i]}";
done
_echo_tabbed "Failed to load ${TXT_YLW}sg${TXT_RST} module. We need it to work with Adaptec controller."
return 1
fi
fi
# Get drives to check
local sgx=''
for sgx in /dev/sg?; do
if smartctl -q silent -i "$sgx"; then
drives+=("$sgx")
fi
done
if [[ ${#drives[@]} -eq 0 ]]; then
_echo_tabbed "Failed to get ${TXT_YLW}/dev/sg?${TXT_RST} drives for Adaptec controller. We have tried ${TXT_YLW}modprobe sg${TXT_RST} but without success. Check it and proceed manually."
return 1
fi
# Form smartd rules
for drive in "${drives[@]}"; do
lines+=("$drive -n standby -s (S/../.././02|L/../../7/03)")
done
# For newer controllers (smartpqi)
elif [[ -d '/sys/bus/pci/drivers/smartpqi' ]]; then
# Get drives to check
mapfile -t < <( arcconf getconfig 1 pd | grep 'Reported Location' | sed -e 's/^.*Slot \([0-9]\).*/\1/g' -e 's/^.*Device \([0-9]\).*/\1/g' ) drives
if [[ ${#drives[@]} -eq 0 ]]; then
_echo_tabbed "Failed to get drives for Adaptec controller. Try to call ${TXT_YLW}arcconf getconfig 1 pd | grep 'Reported Location'${TXT_RST} and check the output."
return 1
fi
# Form smartd rules
for drive in "${drives[@]}"; do
lines+=("/dev/sda -d cciss,$drive -n standby -s (S/../.././02|L/../../7/03)")
done
fi
;;
lsi )
# Get drives to check
mapfile -t < <( megacli -pdlist -a0| awk '/Device Id/ {print $NF}' ) drives
if [[ ${#drives[@]} -eq 0 ]]; then
_echo_tabbed "Failed to get drives for LSI controller. Try to call ${TXT_YLW}megacli -pdlist -a0${TXT_RST} and check the output."
return 1
fi
# Form smartd rules
for drive in "${drives[@]}"; do
lines+=("/dev/sda -d megaraid,${drive} -n standby -s (S/../.././02|L/../../7/03)")
done
;;
* )
_echo_tabbed "Unknown RAID type: ${TXT_YLW}${raid_type}${TXT_RST}. Exiting."
return 1
;;
esac
IFS=$'\n' read -r -d '' smartd_conf <<EOF
$smartd_header
${lines[*]}
EOF
if mv "$smartd_conf_file" "$smartd_conf_backup"; then
_echo_tabbed "Moved ${TXT_YLW}${smartd_conf_file}${TXT_RST} to ${TXT_YLW}${smartd_conf_backup}${TXT_RST}"
else
return 1
fi
if echo "$smartd_conf" > "$smartd_conf_file"; then
_echo_tabbed "Filled ${TXT_YLW}${smartd_conf_file}${TXT_RST}"
return 0
else
return 1
fi
}
# Restart smartd to enable config
_restart_smartd()
{
local os=$1
local restart_cmd=''
case $os in
# systemctl on new OS
Debian[8-9]|Debian1[0-2]|CentOS[7-8]|AlmaLinux[8-9]|Rocky[8-9]|Ubuntu1[6789]|Ubuntu2[0-4] )
restart_cmd='systemctl restart smartd.service'
;;
# /etc/init.d/ on sysv|upstart OS
CentOS6 )
restart_cmd='/etc/init.d/smartd restart'
## On Debian 7 we should always have /etc/init.d/smartmontools while /etc/init.d/smartd can be removed when using backports
;;
Debian[6-7]|Ubuntu12|Ubuntu14 )
# Hack for Debain 6-7
sed -i -e 's/^#start_smartd/start_smartd/' /etc/default/smartmontools
restart_cmd='/etc/init.d/smartmontools restart'
;;
* )
_echo_tabbed "Don't know how to restart smartd on that OS: ${TXT_YLW}${os}${TXT_RST}"
return 1
;;
esac
# Catch error in variable
if IFS=$'\n' result=( $(eval "$restart_cmd" 2>&1) ); then
_echo_tabbed "Smartd started."
return 0
# And output it, if we had nonzero exit code
else
echo
for (( i=0; i<${#result[@]}; i++ )); do
echo "${result[i]}";
done
return 1
fi
}
# Enable autostart of smartd
_enable_smartd_autostart()
{
local os=$1
local enable_cmd=''
case $os in
# systemctl on new OS
Debian[8-9]|Debian1[0-2]|CentOS[7-8]|AlmaLinux[8-9]|Rocky[8-9]|Ubuntu1[6789]|Ubuntu2[0-2] )
enable_cmd='find /usr/lib/systemd/system/ /lib/systemd/system/ /etc/systemd/system/ \
-type f \
\( -name "smartd.service" -or -name "smartmontools.service" \) \
-exec basename \{\} \; |\
uniq |\
xargs systemctl enable'
;;
# systemctl on Ubuntu 24.04
Ubuntu24 )
enable_cmd='systemctl enable smartmontools.service'
;;
# chkconfig on CentOS 6
CentOS6 )
enable_cmd='chkconfig smartd on'
;;
# update-rc.d on sysv/upstart deb-based OS
Debian[6-7]|Ubuntu12|Ubuntu14 )
enable_cmd='update-rc.d smartmontools defaults'
;;
* )
_echo_tabbed "Don't know how to enable smartd autostart on that OS: ${TXT_YLW}${os}${TXT_RST}"
return 1
;;
esac
# Catch error in variable
if IFS=$'\n' result=( $(eval "$enable_cmd" 2>&1) ); then
_echo_tabbed "Smartd autostart enabled."
return 0
# And output it, if we had nonzero exit code
else
echo
for (( i=0; i<${#result[@]}; i++ )); do
echo "${result[i]}";
done
return 1
fi
}
# Run monitoring script
_run_script()
{
local bin_path=$1
local script_name=$2
local mode=$3
if "${bin_path}/${script_name}" --"$mode"; then
return 0
else
_echo_tabbed "Cannot run script in --$mode mode"
return 1
fi
}
# Actual installation
# Detect OS and arch
_detect_os
_detect_arch
echo -e "OS: ${TXT_YLW}${OS} x${ARCH}${TXT_RST}"
# Set OS type
_select_os_type "$OS"
# We should randomize run time to prevent ddos attacks to our gates
# Limit random numbers by 59 minutes
((CRON_MINUTES = RANDOM % 59))
echo -e "Checking dependencies..."
_install_deps "$OS_TYPE"
_echo_result $?
echo -e "Checking for hardware RAID..."
_install_raid_tools "$BIN_PATH" "$REPO_PATH" "$ARCH"
_echo_result $?
echo -e "Installing new smartctl if needed..."
_install_smartctl "$BIN_PATH" "$REPO_PATH" "$ARCH" "$SMARTCTL_STABLE_VERSION" "$SMARTCTL_STABLE_REVISION"
_echo_result $?
echo -e "Installing monitoring script..."
_install_script "$BIN_PATH" "$REPO_PATH" "$SCRIPT_NAME" "$CRON_FILE" "$CRON_MINUTES" "$CRON_HEADER"
_echo_result $?
echo -e "Setting smartd..."
_set_smartd "$RAID_TYPE" "$SMARTD_HEADER" "$OS_TYPE" "$SMARTD_SUFFIX"
_echo_result $?
echo -e "Enabling smartd autostart..."
_enable_smartd_autostart "$OS"
_echo_result $?
echo -e "Starting smartd..."
_restart_smartd "$OS"
_echo_result $?
echo -e "Sending data to FASTVPS monitoring server..."
_run_script "$BIN_PATH" "$SCRIPT_NAME" "cron"
_echo_result $?
echo -e "Current storage status:"
_run_script "$BIN_PATH" "$SCRIPT_NAME" "detect"
echo