mirror of
https://github.com/Spearfoot/disk-burnin-and-testing.git
synced 2025-12-15 15:53:16 +00:00
Fixed problem identifying some mechanical drives as SSDs
Added -x option to control the badblocks -e option, allowing extended testing. Added smartctl to the list of dependencies. Changed disk type detection so that we assume all drives are mechanical drives unless they explicitly return 'Solid State Drive' for Rotational Rate. Removed datestamp from every line of log output, only emitting it in log headers. Minor reformatting.
This commit is contained in:
124
disk-burnin.sh
124
disk-burnin.sh
@@ -1,10 +1,35 @@
|
||||
#!/bin/sh
|
||||
################################################################################
|
||||
#
|
||||
# disk-burnin.sh
|
||||
#
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
# PRE-EXECUTION VALIDATION
|
||||
################################################################################
|
||||
|
||||
# Check if running as root
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "ERROR: Must be run as root" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Check required dependencies
|
||||
readonly DEPENDENCIES="awk badblocks grep sed sleep smartctl"
|
||||
for dependency in ${DEPENDENCIES}; do
|
||||
if ! command -v "${dependency}" > /dev/null 2>&1; then
|
||||
echo "ERROR: Command '${dependency}' not found" >&2
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
|
||||
readonly USAGE=\
|
||||
"NAME
|
||||
$(basename "$0") -- disk burn-in program
|
||||
|
||||
SYNOPSIS
|
||||
$(basename "$0") [-h] [-e] [-f] [-o <directory>] <disk>
|
||||
$(basename "$0") [-h] [-e] [-f] [-o <directory>] [-x] <disk>
|
||||
|
||||
DESCRIPTION
|
||||
A script to simplify the process of burning-in disks. Only intended for use
|
||||
@@ -19,12 +44,13 @@ DESCRIPTION
|
||||
In order to perform tests on drives, you will need to provide the -f option.
|
||||
|
||||
OPTIONS
|
||||
-h show help text
|
||||
-e show extended help text
|
||||
-f run in destructive, non-dry mode
|
||||
-h Show help text
|
||||
-e Show extended help text
|
||||
-f Force script to run in destructive mode
|
||||
ALL DATA ON THE DISK WILL BE LOST!
|
||||
-o <directory> write log files to <directory> (default: $(pwd))
|
||||
<disk> disk to burn-in (/dev/ may be omitted)
|
||||
-o <directory> Write log files to <directory> (default: $(pwd))
|
||||
-x Run full pass of badblocks instead of exiting on first error
|
||||
<disk> Disk to burn-in (/dev/ may be omitted)
|
||||
|
||||
EXAMPLES
|
||||
$(basename "$0") sda
|
||||
@@ -184,14 +210,21 @@ VERSIONS
|
||||
Check for root privileges during runtime.
|
||||
Add option parsing, most notably (-h)elp and -f for non-dry-run mode.
|
||||
Add dry_run_wrapper() function.
|
||||
Add disk type detection to skip badblocks for non-mechanical drives."
|
||||
Add disk type detection to skip badblocks for non-mechanical drives.
|
||||
|
||||
################################################################################
|
||||
# PRE-EXECUTION VALIDATION
|
||||
################################################################################
|
||||
KN, 5 Oct 2020
|
||||
Added -x option to control the badblocks -e option, allowing extended testing.
|
||||
Added smartctl to the list of dependencies.
|
||||
Changed disk type detection so that we assume all drives are mechanical drives
|
||||
unless they explicitly return 'Solid State Drive' for Rotational Rate.
|
||||
Removed datestamp from every line of log output, only emitting it in log headers.
|
||||
Minor reformatting."
|
||||
|
||||
# badblocks default -e option is 1, stop testing if a single error occurs
|
||||
BB_E_ARG=1
|
||||
|
||||
# parse options
|
||||
while getopts ':hefo:' option; do
|
||||
while getopts ':hefo:x' option; do
|
||||
case "${option}" in
|
||||
h) echo "${USAGE}"
|
||||
exit
|
||||
@@ -204,6 +237,8 @@ while getopts ':hefo:' option; do
|
||||
;;
|
||||
o) LOG_DIR="${OPTARG}"
|
||||
;;
|
||||
x) BB_E_ARG=0
|
||||
;;
|
||||
:) printf 'Missing argument for -%s\n' "${OPTARG}" >&2
|
||||
echo "${USAGE}" >&2
|
||||
exit 2
|
||||
@@ -217,30 +252,17 @@ done
|
||||
shift $(( OPTIND - 1 ))
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Missing option: <disk>" >&2
|
||||
echo "ERROR: Missing disk argument" >&2
|
||||
echo "${USAGE}" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Check required dependencies
|
||||
readonly DEPENDENCIES="awk badblocks grep sed sleep"
|
||||
for dependency in ${DEPENDENCIES}; do
|
||||
if ! command -v "${dependency}" > /dev/null 2>&1; then
|
||||
echo "Command '${dependency}' not found" >&2
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
|
||||
# Check if running as root
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "Please run as root" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
# CONSTANTS
|
||||
################################################################################
|
||||
|
||||
readonly BB_E_ARG
|
||||
|
||||
# Drive to burn-in
|
||||
DRIVE="$1"
|
||||
# prepend /dev/ if necessary
|
||||
@@ -249,6 +271,12 @@ if ! printf '%s' "${DRIVE}" | grep "/dev/\w*" > /dev/null 2>&1; then
|
||||
fi
|
||||
readonly DRIVE
|
||||
|
||||
if [ ! -e "$DRIVE" ]; then
|
||||
echo "ERROR: Disk does not exist: $DRIVE" >&2
|
||||
echo "${USAGE}" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Set to working directory if -o <directory> wasn't provided
|
||||
[ -z "${LOG_DIR}" ] && LOG_DIR="$(pwd)"
|
||||
# Trim trailing slashes
|
||||
@@ -314,12 +342,11 @@ DISK_MODEL="$(get_smart_info_value "Device Model")"
|
||||
[ -z "${DISK_MODEL}" ] && DISK_MODEL="$(get_smart_info_value "Model Number")"
|
||||
readonly DISK_MODEL
|
||||
|
||||
# Get disk type
|
||||
# Get disk type; unless we get 'Solid State Device' as return value, assume
|
||||
# we have a mechanical drive.
|
||||
DISK_TYPE="$(get_smart_info_value "Rotation Rate")"
|
||||
if printf '%s' "${DISK_TYPE}" | grep "rpm" > /dev/null 2>&1; then
|
||||
DISK_TYPE="mechanical"
|
||||
else
|
||||
DISK_TYPE="non-mechanical"
|
||||
if printf '%s' "${DISK_TYPE}" | grep -i "solid_state_device" > /dev/null 2>&1; then
|
||||
DISK_TYPE="SSD"
|
||||
fi
|
||||
readonly DISK_TYPE
|
||||
|
||||
@@ -358,10 +385,10 @@ readonly BB_File="${LOG_DIR}/burnin-${DISK_MODEL}_${SERIAL_NUMBER}.bb"
|
||||
# Outputs:
|
||||
# Write message to stdout and log file.
|
||||
##################################################
|
||||
log_info()
|
||||
{
|
||||
now="$(date +"%F %T %Z")"
|
||||
printf "%s\n" "[${now}] $1" | tee -a "${LOG_FILE}"
|
||||
log_info() {
|
||||
# now="$(date +"%F %T %Z")"
|
||||
# printf "%s\n" "[${now}] $1" | tee -a "${LOG_FILE}"
|
||||
printf "%s\n" "$1" | tee -a "${LOG_FILE}"
|
||||
}
|
||||
|
||||
##################################################
|
||||
@@ -369,10 +396,9 @@ log_info()
|
||||
# Arguments:
|
||||
# Message to log.
|
||||
##################################################
|
||||
log_header()
|
||||
{
|
||||
log_header() {
|
||||
log_info "+-----------------------------------------------------------------------------"
|
||||
log_info "+ $1"
|
||||
log_info "+ $1: $(date)"
|
||||
log_info "+-----------------------------------------------------------------------------"
|
||||
}
|
||||
|
||||
@@ -422,8 +448,7 @@ cleanup_log() {
|
||||
# Arguments:
|
||||
# Command to run.
|
||||
##################################################
|
||||
dry_run_wrapper()
|
||||
{
|
||||
dry_run_wrapper() {
|
||||
if [ -z "$DRY_RUN" ]; then
|
||||
log_info "DRY RUN: $*"
|
||||
return 0
|
||||
@@ -451,7 +476,7 @@ dry_run_wrapper()
|
||||
##################################################
|
||||
log_runtime_info() {
|
||||
log_info "Host: ${HOSTNAME}"
|
||||
log_info "OS Flavor: ${OS_FLAVOR}"
|
||||
log_info "OS: ${OS_FLAVOR}"
|
||||
log_info "Drive: ${DRIVE}"
|
||||
log_info "Disk Type: ${DISK_TYPE}"
|
||||
log_info "Drive Model: ${DISK_MODEL}"
|
||||
@@ -476,8 +501,7 @@ log_runtime_info() {
|
||||
# 0 if success or failure.
|
||||
# 1 if timeout threshold exceeded.
|
||||
##################################################
|
||||
poll_selftest_complete()
|
||||
{
|
||||
poll_selftest_complete() {
|
||||
l_poll_duration_seconds=0
|
||||
while [ "${l_poll_duration_seconds}" -lt "${POLL_TIMEOUT_SECONDS}" ]; do
|
||||
smartctl --all "${DRIVE}" \
|
||||
@@ -512,8 +536,7 @@ poll_selftest_complete()
|
||||
# - long
|
||||
# Test duration in seconds.
|
||||
##################################################
|
||||
run_smart_test()
|
||||
{
|
||||
run_smart_test() {
|
||||
log_header "Running SMART $1 test"
|
||||
dry_run_wrapper "smartctl --test=\"$1\" \"${DRIVE}\""
|
||||
log_info "SMART $1 test started, awaiting completion for $2 seconds ..."
|
||||
@@ -533,11 +556,10 @@ run_smart_test()
|
||||
# Arguments:
|
||||
# None
|
||||
##################################################
|
||||
run_badblocks_test()
|
||||
{
|
||||
run_badblocks_test() {
|
||||
log_header "Running badblocks test"
|
||||
if [ "${DISK_TYPE}" = "mechanical" ]; then
|
||||
dry_run_wrapper "badblocks -b 4096 -wsv -e 1 -o \"${BB_File}\" \"${DRIVE}\""
|
||||
if [ "${DISK_TYPE}" != "SSD" ]; then
|
||||
dry_run_wrapper "badblocks -b 4096 -wsv -e ${BB_E_ARG} -o \"${BB_File}\" \"${DRIVE}\""
|
||||
else
|
||||
log_info "SKIPPED: badblocks for ${DISK_TYPE} device"
|
||||
fi
|
||||
@@ -553,7 +575,7 @@ run_badblocks_test()
|
||||
# None
|
||||
##################################################
|
||||
log_full_device_info() {
|
||||
log_header "SMART and non-SMART information"
|
||||
log_header "Drive information"
|
||||
dry_run_wrapper "smartctl --xall --vendorattribute=7,hex48 \"${DRIVE}\" | tee -a \"${LOG_FILE}\""
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user