Purpose
If anyone else buys older drives on eBay, you will soon realise the importance of keeping tabs on your hard drives, quickly. So, i created this to keep track of aging hard drives, but obviously a good idea to keep track with new hard drives also.
Potential improvements
- Organise output based on drive serial (on the todo list one rainy sunday afternoon)
Create Database
I will assume you know how to enter mariadb, if not, i might come back here and update. Inside mariadb
Create database called health
1
CREATE DATABASE health;
Grant permissions to a new user called hdd using a password of mypass (obviously you can use whatever password you desire, and obviously mypass is not a safe password)
1
GRANT SELECT, INSERT,DELETE,UPDATE ON health.* TO hdd IDENTIFIED by 'mypass';
Navigate into the health database
1
use health
Create a table with all the fields required (for my SAS drive script, this is what i’m looking at)
1
CREATE TABLE stats (id INT NOT NULL AUTO_INCREMENT, Date DATE NOT NULL, RawRead INT NOT NULL, ReallocSector INT NOT NULL, SpinRetry INT NOT NULL, CurrPendSect INT NOT NULL, OfflineUncorr INT NOT NULL, HDD VARCHAR(15) NOT NULL, Serial VARCHAR(25) NOT NULL, primary key (id));
Create .my.cnf file in home folder
1
vim $HOME/.my.cnf
Paste into .my.cnf, update with your chosen password
1
2
[client]
password = mypass
The script
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
#!/bin/bash
# Author: Jonny Peace, jonnypeace@outlook.com
d1="/dev/sda"
d2="/dev/sdb"
drive_list="$d1 $d2"
function helper {
echo "Usage:
This script is for 2 x SATA drives.
./health-hdd.sh -h (this helper)
./health-hdd.sh -u (run the updater, and update the database)
./health-hdd.sh -d /dev/sda 4 (will show stats for last 4 drive entries for /dev/sda)
./health-hdd.sh -a (will show the entire table organised by drive)
./health-hdd.sh -l 4 (will show the last 4 entries)"
}
# Shows all health, drives separated
function all_health {
for i in $drive_list
do
mariadb health -u hdd -e "SELECT * FROM stats WHERE hdd = '$i'"
echo
done
}
# Shows the last entries, defined by a number on the command line
function last_lot {
for i in $drive_list
do
mariadb health -u hdd -e "SELECT * FROM (
SELECT * FROM stats WHERE hdd = '$i' ORDER BY id DESC LIMIT $number
)Var1
ORDER BY id ASC;"
done
}
# Shows only one specific drive
function drive_hdd {
if [[ $args == 3 ]]
then
mariadb health -u hdd -e "SELECT * FROM (
SELECT * FROM stats WHERE hdd = '$drive_num' ORDER BY id DESC LIMIT $number
)Var1
ORDER BY id ASC;"
elif [[ $args == 2 ]]
then
mariadb health -u hdd -e "SELECT * FROM stats WHERE hdd = '$drive_num'"
else
helper
fi
}
# Updates the database with new data from smartctl
function updater {
now=$(printf '%(%Y-%m-%d)T\n')
for i in $drive_list
do
mapfile -t -d'\n' array < <(smartctl -a "$i")
# raw read
raw_read=$(awk '/Raw_Read_Error_Rate/{print $10}' <<< "${array[@]}")
# reallocated sector count
real_sect=$(awk '/Reallocated_Event_Count/{print $10}' <<< "${array[@]}")
# spin retries
spin_retry=$(awk '/Spin_Retry_Count/{print $10}' <<< "${array[@]}")
# offline uncorrectable
off_uncor=$(awk '/Offline_Uncorrectable/{print $10}' <<< "${array[@]}")
# current pending sectors
curr_pend_sect=$(awk '/Current_Pending_Sector/{print $10}' <<< "${array[@]}")
# serial
serial=$(awk '/Serial Number:/{print $3}' <<< "${array[@]}")
statement="INSERT INTO stats (Date,RawRead,SpinRetry,ReallocSector,HDD,OfflineUncorr,CurrPendSect,Serial) VALUES
('$now', '$raw_read', '$spin_retry', '$real_sect', '$i', '$off_uncor', '$curr_pend_sect', '$serial')"
mariadb health -u hdd << EOF
$statement
EOF
if [[ $? == 0 ]]
then
printf '\n%s\n\n' "Data added successfully for $i"
mariadb health -u hdd -e "SELECT * FROM stats WHERE hdd = '$i'"
else
echo "Something went wrong"
fi
done
}
while getopts ahl:d:2u opt
do
case "$opt" in
a) all_health ;;
h) helper ;;
l) number=$2
last_lot ;;
d) drive_num=$2
args=$#
number=$3
drive_hdd ;;
u) updater ;;
*) helper
esac
done