Home SATA 2 x Drive Health Database
Post
Cancel

SATA 2 x Drive Health Database

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

This post is licensed under CC BY 4.0 by the author.