HDD Tray ermitteln LED blinken
Beschreibung:
Es gibt ein tolles tool. Mit der man die LED zum Tray blinken lassen kann.
Noch ein kleines Script dazu wo man nur dass device angeben muss.
Durchführung:
apt-get install -y lsscsi sg3-utils
Festplatten anzeigen lassen:
lsscsi -g
Ausgabe:
[1:0:0:0] cd/dvd Slimtype DVD A DS8ACSH LP5M /dev/sr0 /dev/sg17
[3:0:0:0] disk SEAGATE XS400ME70004 0004 /dev/sda /dev/sg0
[3:0:1:0] disk SEAGATE ST20000NM002D E004 /dev/sdb /dev/sg1
[3:0:2:0] disk WDC WUS721010AL5204 C980 /dev/sdc /dev/sg2
[3:0:3:0] disk SEAGATE ST20000NM002D E006 /dev/sdd /dev/sg3
[3:0:4:0] disk WDC WUS721010AL5204 C980 /dev/sde /dev/sg4
[3:0:5:0] disk SEAGATE ST20000NM002D E006 /dev/sdf /dev/sg5
[3:0:6:0] disk WDC WUS721010AL5204 C980 /dev/sdg /dev/sg6
[3:0:7:0] disk WDC WUS721010AL5204 C980 /dev/sdh /dev/sg7
[3:0:8:0] disk WDC WUS721010AL5204 C980 /dev/sdi /dev/sg8
[3:0:9:0] disk WDC WUS721010AL5204 C980 /dev/sdj /dev/sg9
[3:0:10:0] disk WDC WUS721010AL5204 C980 /dev/sdk /dev/sg10
[3:0:11:0] disk SEAGATE XS400ME70004 0004 /dev/sdl /dev/sg11
[3:0:12:0] disk WDC WUS721010AL5204 C980 /dev/sdm /dev/sg12
[3:0:13:0] disk WDC WUS721010AL5204 C980 /dev/sdn /dev/sg13
[3:0:14:0] disk WDC WUS721010AL5204 C980 /dev/sdo /dev/sg14
[3:0:15:0] disk WDC WUS721010AL5204 C980 /dev/sdp /dev/sg15
[3:0:16:0] enclosu BROADCOM VirtualSES 03 - /dev/sg16
[4:0:0:0] cd/dvd AMI Virtual CDROM0 1.00 /dev/sr1 /dev/sg18
Script:
nano /usr/local/bin/identify-disk.sh
Inhalt
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<USAGE
Usage:
identify-disk [--on|--off|--blink SECONDS] [--symlink|--ses] /dev/sdX|sdX|sdXn
Optionen:
--on / --off / --blink SECONDS LED steuern
--symlink nur sysfs/enclosure_device* nutzen
--ses nur SES (sg_ses) nutzen
(ohne Methode) auto: erst symlink, dann SES-Fallback
Beispiele:
identify-disk --on /dev/sdfsdi
identify-disk --blink 10 sdg8
identify-disk --off sdg--symlink sdi
identify-disk --blinkon 15--ses sdg8 # Partition ok, wird zu sdg normalisiertsdi
USAGE
}
MODE="on";
BLINK_SECS=0
METHOD="auto" # auto | symlink | ses
[[ $# -lt 1 ]] && { usage; exit 1; }
while [[ $# -gt 0 ]]; do
case "${1:-}" in
--on) MODE="on"; shift ;;
--off) MODE="off"; shift ;;
--blink) MODE="blink"; BLINK_SECS="${2:-}"; [[ -z "$BLINK_SECS" ]] && { echo "Fehlende Sekunden bei --blink"; exit 1; }; shift 2 ;;
--symlink) METHOD="symlink"; shift ;;
--ses) METHOD="ses"; shift ;;
-h|--help) usage; exit 0 ;;
*) DISK="$1"; shift ;;
esac
done
command# -v-- lsscsiDevice >/dev/null || { echo "lsscsi fehlt"; exit 1; }
command -v sg_ses >/dev/null || { echo "sg3-utilsnormalisieren (sg_ses)Partitionen fehlt"; exit 1; }
#abschneiden, /dev/ Präfix + Partitionen weg (sdg8hinzufügen) -> sdg)--
[[ "$DISK" =~ ^sd ]] && DISK="/dev/$DISK"
BASE="$(basename "$DISK")"
BASE_NOPART="${BASE%%[0-9]*}"
# strip trailing digits
DISK="/dev/$BASE_NOPART"
[[ -eb "$DISK" ]] || { echo "Gerät nicht gefunden: $DISK"; exit 1; }
#do_symlink() Zeile{
inlocal lsscsip="/sys/class/block/${BASE_NOPART}/device"
findenlocal –enc=( robust: /dev/sdX als eigenes Feld, nicht am Zeilenende
LINE="$(lsscsip"/enclosure_device* -g | awk -v d="$DISK" '$0 ~ ("[[:space:]]" d "[[:space:]]"){print; exit}')"
if
[[ -ze "$LINE"{enc[0]}" ]] || { echo "Kein enclosure_device* für $DISK gefunden."; thenreturn #2; Fallback}
local LOCATE="${enc[0]}/locate"
[[ -w "$LOCATE" ]] || { echo "'locate' nicht verfügbar/schreibbar unter ${enc[0]}."; return 3; }
local SLOT_FILE="${enc[0]}/slot"
local slot="$(cat "$SLOT_FILE" 2>/dev/null || echo "?")"
case "$MODE" in
on) echo 1 | sudo tee "$LOCATE" >/dev/null; echo "Identify-LED an (mancheSlot lsscsi-Formate):$slot prüfevia explizitsysfs daslocate) Blockdev-Feld– $DISK";;
off) echo 0 | sudo tee "$LOCATE" >/dev/null; echo "Identify-LED aus (Slot $slot via sysfs locate) – $DISK";;
blink) echo 1 | sudo tee "$LOCATE" >/dev/null; echo "Identify-LED an (Slot $slot) – blinke $BLINK_SECS s…"; sleep "$BLINK_SECS"; echo 0 | sudo tee "$LOCATE" >/dev/null; echo "Identify-LED wieder aus.";;
esac
}
do_ses() {
command -v lsscsi >/dev/null 2>&1 || { echo "lsscsi fehlt (apt install lsscsi)"; return 4; }
command -v sg_ses >/dev/null 2>&1 || { echo "sg3-utils (sg_ses) fehlt (apt install sg3-utils)"; return 5; }
local LINE
LINE="$(lsscsi -g | awk -v d="$DISK" '{if ($(NF-1)==d) {print; exit}}')"
fi
[[ -n "$LINE" ]] || { echo "Konnte $DISK nicht in 'lsscsi -gg' finden."; exitreturn 1;6; }
# H:B:T:L extrahieren
if [[ "$LINE" =~ \[([0-9]+):([0-9]+):([0-9]+):([0-9]+)\] ]]; then
local HOST="${BASH_REMATCH[1]}"; BUS="${BASH_REMATCH[2]}"; TARGET="${BASH_REMATCH[3]}"; LUN="${BASH_REMATCH[4]}"
else
echo "Konnte SCSI-Adresse nicht parsen."; exitreturn 17
fi
#local PassendesSES_LINE SES (enclosure) auf gleichem Host:BusSES_DEV
SES_LINE="$(lsscsi -g | awk -v h="$HOST" -v b="$BUS" '$2=="enclosu" && $1 ~ ("\\["h":"b":"){print; exit}')"
[[ -n "$SES_LINE" ]] || { echo "Kein SES/Enclosure auf ${HOST}:${BUS} gefunden (HW-RAID? NutzeHersteller-CLI Hersteller-CLI)nötig)."; exitreturn 1;8; }
SES_DEV="$(echo "$SES_LINE" | awk '{print $NF}')"
[[ -e "$SES_DEV" ]] || { echo "SES-Gerät existiert nicht: $SES_DEV"; exitreturn 1;9; }
local SAS_PATH="/sys/class/scsi_device/${HOST}:${BUS}:${TARGET}:${LUN}/device/sas_address"
if [[ ! -r "$SAS_PATH" ]]; then
echo "Konnte SAS-Adresse nicht aus $SAS_PATH lesen."; return 10
fi
local DISK_SAS; DISK_SAS="$(tr -d '\n' < "$SAS_PATH")"
[[ -n "$DISK_SAS" ]] || { echo "Leere SAS-Adresse gelesen."; return 11; }
# passender SES-Index über sg_ses -p aes via SAS address
local INDEX
INDEX="$(sg_ses -p aes "$SES_DEV" 2>/dev/null \
| awk -v want="$DISK_SAS" '
/Element index:/ {idx=$3; gsub(":","",idx)}
/SAS address:/ && $3 ~ /^0x/ {sas=$3; if (tolower(sas)==tolower(want)) {print idx; exit}}
')"
# Fallback über physische Slotnummer, falls SAS-Match nicht gefunden wurde
if [[ -z "$INDEX" ]]; then
local p="/sys/class/block/${BASE_NOPART}/device"
local enc=( "$p"/enclosure_device* )
if [[ -e "${enc[0]}" && -r "${enc[0]}/slot" ]]; then
local PHY_SLOT; PHY_SLOT="$(cat "${enc[0]}/slot" 2>/dev/null || true)"
if [[ -n "$PHY_SLOT" ]]; then
INDEX="$(sg_ses -p aes "$SES_DEV" 2>/dev/null \
| awk -v slot="$PHY_SLOT" '
/Element index:/ {idx=$3; gsub(":","",idx)}
/device slot number:/ {if ($5==slot) {print idx; exit}}
')"
fi
fi
fi
[[ -n "$INDEX" ]] || { echo "Konnte passenden SES-Index nicht ermitteln (SAS/slot-Mapping fehlgeschlagen)."; return 12; }
case "$MODE" in
on) sg_ses --index="$TARGET"INDEX" --set=ident "$SES_DEV"; echo "Identify-LED an: SlotSES index $TARGETINDEX (Disk $DISK) übervia $SES_DEV";;
off) sg_ses --index="$TARGET"INDEX" --clear=ident "$SES_DEV"; echo "Identify-LED aus: SlotSES index $TARGETINDEX (Disk $DISK) übervia $SES_DEV";;
blink) sg_ses --index="$TARGET"INDEX" --set=ident "$SES_DEV"; echo "LED an für $BLINK_SECS s: SlotSES index $TARGETINDEX (Disk $DISK)"; sleep "$BLINK_SECS"; sg_ses --index="$TARGET"INDEX" --clear=ident "$SES_DEV"; echo "LED aus.";;
esac
}
case "$METHOD" in
symlink)
do_symlink || exit $?
;;
ses)
do_ses || exit $?
;;
auto)
if do_symlink; then
exit 0
else
echo "(Auto) Fallback auf SES…"
do_ses
fi
;;
*)
echo "Unbekannte Methode: $METHOD"; usage; exit 1 ;;
esac
Ausführbar machen
chmod +x /usr/local/bin/identify-disk.sh
Hilfe/Bedienung
Usage:sage:
identify-disk [--on|--off|--blink SECONDS] [--symlink|--ses] /dev/sdX|sdX|sdXn
Optionen:
--on / --off / --blink SECONDS LED steuern
--symlink nur sysfs/enclosure_device* nutzen
--ses nur SES (sg_ses) nutzen
(ohne Methode) auto: erst symlink, dann SES-Fallback
Beispiele:
identify-disk --on /dev/sdfsdi
identify-disk --blink 10 sdg8
identify-disk --off sdg--symlink sdi
identify-disk --blinkon 15--ses sdg8 # Partition ok, wird zu sdg normalisiertsdi
Alte Laufwerke entfernen:
Sobald alte Laufwerke entfernt werden, bleiben Sie tot in der Liste.
Erst Laufwerk entfernen. Dann neu einschieben.
Das machen wir wieder mit einem script. Das Script wartet solange bis wir die festplatte getauscht haben.
wenn getauscht bestätigen.
nano /usr/local/bin/scsi-hotswap.sh
Inhalt
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -ne 1 ]]; then
echo "Usage: $0 /dev/sdX"
exit 1
fi
DISK="$1"
# Normalisieren: Partitionen abschneiden, /dev/ hinzufügen falls nötig
[[ "$DISK" =~ ^sd ]] && DISK="/dev/$DISK"
BASE_NOPART="${DISK%%[0-9]*}"
DISK="$BASE_NOPART"
if [[ ! -b "$DISK" ]]; then
echo "Fehler: Gerät $DISK existiert nicht oder ist kein Blockdevice."
exit 1
fi
# lsscsi muss installiert sein
command -v lsscsi >/dev/null || { echo "Bitte installiere lsscsi (apt install lsscsi)"; exit 1; }
# Host:Bus:Target:LUN ermitteln
LINE="$(lsscsi -g | awk -v d="$DISK" '{if ($(NF-1)==d) {print; exit}}')"
if [[ -z "$LINE" ]]; then
echo "Konnte $DISK nicht in lsscsi -g finden."
exit 1
fi
if [[ "$LINE" =~ \[([0-9]+):([0-9]+):([0-9]+):([0-9]+)\] ]]; then
HOST="${BASH_REMATCH[1]}"
BUS="${BASH_REMATCH[2]}"
TARGET="${BASH_REMATCH[3]}"
LUN="${BASH_REMATCH[4]}"
else
echo "Konnte SCSI-Adresse nicht parsen."
exit 1
fi
echo ">>> Entferne $DISK (SCSI $HOST:$BUS:$TARGET:$LUN)"
echo 1 | sudo tee /sys/class/scsi_device/${HOST}:${BUS}:${TARGET}:${LUN}/device/delete >/dev/null
echo ">>> Bitte neue Festplatte in Slot ${TARGET} einsetzen..."
read -p "Weiter mit ENTER, wenn neue Platte steckt."
echo ">>> Rescanne Slot $TARGET..."
echo "${HOST} ${BUS} ${TARGET}" | sudo tee /sys/class/scsi_host/host${HOST}/scan >/dev/null
echo ">>> Neue Device-Liste:"
lsscsi -g | grep "\[${HOST}:${BUS}:${TARGET}:"
Nun noch ausführbar machen
chmod +x /usr/local/bin/scsi-hotswap.sh
Hilfe/Benutzung:
Usage: /usr/local/bin/scsi-hotswap.sh /dev/sdX
Ausgabe:
root@backupsrv001:~# scsi-hotswap.sh /dev/sdq
>>> Entferne /dev/sdq (SCSI 3:0:17:0)
>>> Bitte neue Festplatte in Slot 17 einsetzen...
Weiter mit ENTER, wenn neue Platte steckt.
>>> Rescanne Slot 17...
>>> Neue Device-Liste: