| Line 5... |
Line 5... |
| 5 |
# Copyright (c) 2005,2006: Ira W. Snyder (devel@irasnyder.com)
|
5 |
# Copyright (c) 2005,2006: Ira W. Snyder (devel@irasnyder.com)
|
| 6 |
# License: GNU General Public License v2 (or at your option, any later version)
|
6 |
# License: GNU General Public License v2 (or at your option, any later version)
|
| 7 |
#
|
7 |
#
|
| 8 |
################################################################################
|
8 |
################################################################################
|
| 9 |
|
9 |
|
| 10 |
# This script needs dd, mktemp, smartctl, cstream, mailx, tee, sleep, echo,
|
10 |
# This script needs mktemp, smartctl, mailx, tee, sleep, echo,
|
| 11 |
# date, hostname, and rm in your path in order to work at all.
|
11 |
# date, hostname, and rm in your path in order to work.
|
| 12 |
|
12 |
|
| 13 |
################################################################################
|
13 |
################################################################################
|
| 14 |
### Config Options ###
|
14 |
### Config Options ###
|
| 15 |
################################################################################
|
15 |
################################################################################
|
| 16 |
|
16 |
|
| 17 |
TMPFILE="$(mktemp)" || (echo "Failed to create tempfile" && exit 1)
|
17 |
TMPFILE="$(mktemp)" || (echo "Failed to create tempfile" && exit 1)
|
| 18 |
EMAIL_ADDR="ira@irasnyder.com"
|
18 |
EMAIL_ADDR=""
|
| 19 |
EMAIL_FILE="${TMPFILE}"
|
19 |
EMAIL_FILE="${TMPFILE}"
|
| 20 |
RAID_DEVICE="/dev/md0"
|
20 |
RAID_DEVICE="/dev/md0"
|
| 21 |
RAID_DRIVES="/dev/sd[abcdefgh]"
|
21 |
RAID_DRIVE_BASE="/dev/sd"
|
| 22 |
DD_SPD_LIMIT="80M"
|
22 |
RAID_DRIVE_LETTERS="a b c d e f g h"
|
| 23 |
SMART_SLEEP_TIME="160m"
|
23 |
SMART_SLEEP_TIME="160m"
|
| 24 |
|
24 |
|
| - |
|
25 |
# Call clean_up() on interrupt
|
| - |
|
26 |
trap clean_up SIGHUP SIGINT SIGTERM
|
| - |
|
27 |
|
| 25 |
################################################################################
|
28 |
################################################################################
|
| 26 |
### Functions ###
|
29 |
### Functions ###
|
| 27 |
################################################################################
|
30 |
################################################################################
|
| 28 |
|
31 |
|
| 29 |
# Anything that needs to be run before the main program starts
|
32 |
# Anything that needs to be run before the main program starts
|
| Line 32... |
Line 35... |
| 32 |
}
|
35 |
}
|
| 33 |
|
36 |
|
| 34 |
# Anything that needs to be run after the main program finishes
|
37 |
# Anything that needs to be run after the main program finishes
|
| 35 |
# goes in this function
|
38 |
# goes in this function
|
| 36 |
function clean_up () {
|
39 |
function clean_up () {
|
| - |
|
40 |
for l in $RAID_DRIVE_LETTERS; do
|
| - |
|
41 |
remove_file "${EMAIL_FILE}.${l}"
|
| - |
|
42 |
done
|
| - |
|
43 |
|
| - |
|
44 |
remove_file "${EMAIL_FILE}"
|
| - |
|
45 |
}
|
| - |
|
46 |
|
| - |
|
47 |
function remove_file () {
|
| 37 |
if [ -f "$EMAIL_FILE"]; then
|
48 |
if [ -f "$1" ]; then
|
| 38 |
echo "Removing: $EMAIL_FILE";
|
49 |
echo "Removing: $1"
|
| 39 |
rm "$EMAIL_FILE";
|
50 |
rm "$1"
|
| 40 |
fi
|
51 |
fi
|
| 41 |
}
|
52 |
}
|
| 42 |
|
53 |
|
| 43 |
# Generate a nice header for the email
|
54 |
# Generate a nice header for the email
|
| 44 |
function generate_header () {
|
55 |
function generate_header () {
|
| Line 62... |
Line 73... |
| 62 |
START_TIME="$(date)"
|
73 |
START_TIME="$(date)"
|
| 63 |
|
74 |
|
| 64 |
### Optional stuff, disabled for now, since you MUST be offline to perform
|
75 |
### Optional stuff, disabled for now, since you MUST be offline to perform
|
| 65 |
### both checks, and I don't want to have to go offline once a month.
|
76 |
### both checks, and I don't want to have to go offline once a month.
|
| 66 |
|
77 |
|
| - |
|
78 |
# Run smartctl on each drive, giving the output to a different file
|
| 67 |
# Check via read test
|
79 |
# for each drive
|
| - |
|
80 |
for l in $RAID_DRIVE_LETTERS; do
|
| 68 |
# echo "Running read-only check: e2fsck -c $RAID_DEVICE" | tee -a "$EMAIL_FILE"
|
81 |
DRIVE="${RAID_DRIVE_BASE}${l}"
|
| 69 |
# e2fsck -c "$RAID_DEVICE" 2>&1 | tee -a "$EMAIL_FILE"
|
82 |
DRIVE_FILE="${EMAIL_FILE}.${l}"
|
| 70 |
|
83 |
|
| 71 |
# Check via non-destructive read-write test
|
84 |
echo "SMART checking drive: ${DRIVE}" | tee -a "$DRIVE_FILE"
|
| 72 |
# echo "Running non-destructive read-write check: e2fsck -c -c $RAID_DEVICE" | tee -a "$EMAIL_FILE"
|
85 |
echo "=================================================" | tee -a "$DRIVE_FILE"
|
| 73 |
# e2fsck -c -c "$RAID_DEVICE" 2>&1 | tee -a "$EMAIL_FILE"
|
86 |
smartctl -t long "${DRIVE}" 2>&1 | tee -a "$DRIVE_FILE"
|
| 74 |
|
- |
|
| 75 |
# Read the whole disk. As of linux-2.6.15, md will regenerate bad data on
|
- |
|
| 76 |
# a read error, then schedule a write of the good data back to disk. It
|
87 |
echo | tee -a "$DRIVE_FILE"
|
| 77 |
# should then re-read the newly written data to make sure it's ok.
|
88 |
echo | tee -a "$DRIVE_FILE"
|
| 78 |
#
|
89 |
done
|
| 79 |
# Source: http://www.ussg.iu.edu/hypermail/linux/kernel/0601.2/1200.html
|
- |
|
| 80 |
#
|
90 |
|
| 81 |
echo "Reading the whole disk: dd if=${RAID_DEVICE} of=/dev/null" | tee -a "$EMAIL_FILE"
|
91 |
# Sleep to give time for all drives to do their thing
|
| 82 |
dd if="${RAID_DEVICE}" | cstream -t"${DD_SPD_LIMIT}" -T300 -v1 -o- | tee -a "$EMAIL_FILE"
|
- |
|
| 83 |
echo | tee -a "$EMAIL_FILE"
|
- |
|
| 84 |
echo | tee -a "$EMAIL_FILE"
|
92 |
sleep "${SMART_SLEEP_TIME}"
|
| 85 |
|
93 |
|
| 86 |
# Run smartctl on each drive, sleeping in between each one
|
94 |
# Get the results of thest for each drive, giving the output to a different
|
| - |
|
95 |
# file for each drive
|
| 87 |
for d in $RAID_DRIVES;
|
96 |
for l in $RAID_DRIVE_LETTERS; do
|
| 88 |
do echo "SMART checking drive: ${d}" | tee -a "$EMAIL_FILE"
|
97 |
DRIVE="${RAID_DRIVE_BASE}${l}"
|
| 89 |
echo "=================================================" | tee -a "$EMAIL_FILE"
|
98 |
DRIVE_FILE="${EMAIL_FILE}.${l}"
|
| - |
|
99 |
|
| 90 |
smartctl -t long "${d}" 2>&1 | tee -a "$EMAIL_FILE"
|
100 |
smartctl -d ata -l selftest "${DRIVE}" 2>&1 | tee -a "$DRIVE_FILE"
|
| 91 |
echo | tee -a "$EMAIL_FILE"
|
101 |
echo | tee -a "$DRIVE_FILE"
|
| 92 |
echo | tee -a "$EMAIL_FILE"
|
102 |
echo | tee -a "$DRIVE_FILE"
|
| - |
|
103 |
done
|
| - |
|
104 |
|
| 93 |
sleep "${SMART_SLEEP_TIME}"
|
105 |
# Accumulate the results into the main file
|
| 94 |
smartctl -d ata -l selftest "${d}" 2>&1 | tee -a "$EMAIL_FILE"
|
106 |
for l in $RAID_DRIVE_LETTERS; do
|
| 95 |
echo | tee -a "$EMAIL_FILE"
|
107 |
DRIVE_FILE="${EMAIL_FILE}.${l}"
|
| - |
|
108 |
|
| 96 |
echo | tee -a "$EMAIL_FILE"
|
109 |
cat "$DRIVE_FILE" >> "$EMAIL_FILE"
|
| 97 |
done;
|
110 |
done
|
| 98 |
|
111 |
|
| 99 |
# Get finish date / time
|
112 |
# Get finish date / time
|
| 100 |
FINISH_TIME="$(date)"
|
113 |
FINISH_TIME="$(date)"
|
| 101 |
|
114 |
|
| 102 |
# Print the final bits to the email
|
115 |
# Print the final bits to the email
|
| Line 104... |
Line 117... |
| 104 |
echo "Finish time: ${FINISH_TIME}" | tee -a "$EMAIL_FILE"
|
117 |
echo "Finish time: ${FINISH_TIME}" | tee -a "$EMAIL_FILE"
|
| 105 |
|
118 |
|
| 106 |
# Mail out the file
|
119 |
# Mail out the file
|
| 107 |
mailx -s "RAID Check Results from: $(hostname --fqdn)" "$EMAIL_ADDR" < "$EMAIL_FILE"
|
120 |
mailx -s "RAID Check Results from: $(hostname --fqdn)" "$EMAIL_ADDR" < "$EMAIL_FILE"
|
| 108 |
|
121 |
|
| 109 |
# Clean up the email file, etc.
|
122 |
# Clean up the email files, etc.
|
| 110 |
clean_up
|
123 |
clean_up
|
| 111 |
|
124 |
|