HDD Tray ermitteln LED blinken und/oder austauschen
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.Ein weiteres script zum Datenträger tausch.
Lässt slot blinken.
festplatte tauschen
Alte festplatte wird deregistriert und neue hinzugefügt.
LED ausgeschaltet.
BAM
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 sdi
identify-disk --blink 10 sdg8
identify-disk --off --symlink sdi
identify-disk --on --ses sdi
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
# --- Device normalisieren (Partitionen abschneiden, /dev/ hinzufügen) ---
[[ "$DISK" =~ ^sd ]] && DISK="/dev/$DISK"
BASE="$(basename "$DISK")"
BASE_NOPART="${BASE%%[0-9]*}"
DISK="/dev/$BASE_NOPART"
[[ -b "$DISK" ]] || { echo "Gerät nicht gefunden: $DISK"; exit 1; }
do_symlink() {
local p="/sys/class/block/${BASE_NOPART}/device"
local enc=( "$p"/enclosure_device* )
[[ -e "${enc[0]}" ]] || { echo "Kein enclosure_device* für $DISK gefunden."; return 2; }
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 (Slot $slot via sysfs locate) – $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}}')"
[[ -n "$LINE" ]] || { echo "Konnte $DISK nicht in 'lsscsi -g' finden."; return 6; }
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."; return 7
fi
local SES_LINE SES_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? Hersteller-CLI nötig)."; return 8; }
SES_DEV="$(echo "$SES_LINE" | awk '{print $NF}')"
[[ -e "$SES_DEV" ]] || { echo "SES-Gerät existiert nicht: $SES_DEV"; return 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="$INDEX" --set=ident "$SES_DEV"; echo "Identify-LED an: SES index $INDEX (Disk $DISK) via $SES_DEV";;
off) sg_ses --index="$INDEX" --clear=ident "$SES_DEV"; echo "Identify-LED aus: SES index $INDEX (Disk $DISK) via $SES_DEV";;
blink) sg_ses --index="$INDEX" --set=ident "$SES_DEV"; echo "LED an für $BLINK_SECS s: SES index $INDEX (Disk $DISK)"; sleep "$BLINK_SECS"; sg_ses --index="$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
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 sdi
identify-disk --blink 10 sdg8
identify-disk --off --symlink sdi
identify-disk --on --ses sdi
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
usage() {
cat <<USAGE
Usage:
scsi-hotswap [--method auto|symlink|ses] [--blink N|--no-led] [--no-prompt] /dev/sdX|sdX|sdXn
Optionen:
--method M M = auto (default) | symlink | ses
--blink N LED vor dem Tausch N Sekunden blinken (statt dauerhaft an)
--no-led keine LED-Steuerung
--no-prompt nicht auf ENTER warten (setze voraus, dass neue Platte schon steckt)
Beispiele:
scsi-hotswap sdi
scsi-hotswap --method symlink --blink 8 sdg8
scsi-hotswap --method ses --no-prompt sdm
USAGE
}
METHOD="auto" # auto | symlink | ses
BLINK_SECS=0 # 0 = steady on
USE_LED=1
PROMPT=1
[[ $# -lt 1 ]] && { usage; exit 1; }
while [[ $# -gt 0 ]]; do
case "${1:-}" in
--method) METHOD="${2:-}"; shift 2 ;;
--blink) BLINK_SECS="${2:-}"; [[ -z "$BLINK_SECS" ]] && { echo "Fehlende Sekunden bei --blink"; exit 1; }; shift 2 ;;
--no-led) USE_LED=0; shift ;;
--no-prompt) PROMPT=0; shift ;;
-h|--help) usage; exit 0 ;;
*) DISK="$1"; shift ;;
esac
done
# --- Device normalisieren ---
[[ "$DISK" =~ ^sd ]] && DISK="/dev/$DISK"
BASE="$(basename "$DISK")"
BASE_NOPART="${BASE%%[0-9]*}"
DISK="/dev/$BASE_NOPART"
[[ -b "$DISK" ]] || { echo "Gerät nicht gefunden: $DISK"; exit 1; }
need() { command -v "$1" >/dev/null 2>&1 || { echo "$1 fehlt. Bitte installieren."; exit 1; }; }
# --------------------------
# LED via sysfs (symlink-Weg)
# --------------------------
# merkt sich LOCATE_PATH_CACHED+SLOT_CACHED, damit "off" nach dem Swap immer klappt
LOCATE_PATH_CACHED=""
SLOT_CACHED=""
led_symlink() {
local mode="$1" # on|off|blink
local LOCATE_PATH=""
local SLOT=""
# bereits gecachten Pfad benutzen, wenn vorhanden
if [[ -n "$LOCATE_PATH_CACHED" && -e "$LOCATE_PATH_CACHED" ]]; then
LOCATE_PATH="$LOCATE_PATH_CACHED"
SLOT="$SLOT_CACHED"
else
local p="/sys/class/block/${BASE_NOPART}/device"
local enc=( "$p"/enclosure_device* )
[[ -e "${enc[0]}" ]] || return 2
LOCATE_PATH="${enc[0]}/locate"
[[ -w "$LOCATE_PATH" ]] || return 3
SLOT="$(cat "${enc[0]}/slot" 2>/dev/null || echo "?")"
LOCATE_PATH_CACHED="$LOCATE_PATH"
SLOT_CACHED="$SLOT"
fi
local slot_label=""
[[ -n "$SLOT" ]] && slot_label=" (Slot $SLOT)"
case "$mode" in
on)
echo 1 | sudo tee "$LOCATE_PATH" >/dev/null
echo "LED an (Slot $SLOTan${slot_label} via sysfs)sysfs – $DISK"
;;
off)
echo 0 | sudo tee "$LOCATE_PATH" >/dev/null
echo "LED aus (Slot $SLOTaus${slot_label} via sysfs)sysfs – $DISK"
;;
blink)
echo 1 | sudo tee "$LOCATE_PATH" >/dev/null
echo "LED an (Slot $SLOT)an${slot_label} – blinke ${BLINK_SECS}s…"
sleep "$BLINK_SECS"
echo 0 | sudo tee "$LOCATE_PATH" >/dev/null
echo "LED aus."
;;
esac
return 0
}
# -------------------------------------------
# SES-Index + Slotnummer + SES-Device ermitteln (per SAS)
# -------------------------------------------
get_ses_index() {
# Outputs (echo): "<SES_DEV> <INDEX> <SLOTNUM> <HOST> <BUS> <TARGET> <LUN>"
need lsscsi; need sg_ses
local LINE
LINE="$(lsscsi -g | awk -v d="$DISK" '{if ($(NF-1)==d) {print; exit}}')"
[[ -n "$LINE" ]] || { echo "Konnte $DISK nicht in 'lsscsi -g' finden." >&2; return 1; }
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." >&2; return 1
fi
local SES_LINE SES_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?)." >&2; return 1; }
SES_DEV="$(echo "$SES_LINE" | awk '{print $NF}')"
[[ -e "$SES_DEV" ]] || { echo "SES-Gerät existiert nicht: $SES_DEV" >&2; return 1; }
local SAS_PATH="/sys/class/scsi_device/${HOST}:${BUS}:${TARGET}:${LUN}/device/sas_address"
[[ -r "$SAS_PATH" ]] || { echo "SAS-Adresse nicht lesbar: $SAS_PATH" >&2; return 1; }
local DISK_SAS; DISK_SAS="$(tr -d '\n' < "$SAS_PATH")"
[[ -n "$DISK_SAS" ]] || { echo "Leere SAS-Adresse." >&2; return 1; }
# In einem Durchlauf: Index + physische Slotnummer zu *dieser* Disk finden
local INDEX INDEX="$SLOTNUM
read INDEX SLOTNUM < <(sg_ses -p aes "$SES_DEV" 2>/dev/null \
| awk -v want="$DISK_SAS" '
/Element index:/ {idx=$3; gsub(":","",idx); slot=""}
/device slot number:/ {slot=$5}
/SAS address:/ && $3 ~ /^0x/ {sas=$3; if (tolower(sas)==tolower(want)) {print idx;idx, slot; exit}}
')"
# Fallback viaüber physischemphysische SlotSlotnummer aus sysfs (falls sysfs-slot verfügbar)vorhanden)
if [[ -z "$INDEX"{INDEX:-}" || -z "${SLOTNUM:-}" ]]; 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
SLOTNUM="$PHY_SLOT"
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
# Es kann vorkommen, dass SLOTNUM leer bleibt → ist ok; dann nur Index nutzen
[[ -n "$INDEX" ]] || { echo "SES-Index konnte nicht ermittelt werden." >&2; return 1; }
echo "$SES_DEVSES_DEV" "$INDEXINDEX" "$HOST{SLOTNUM:-}" "$BUSHOST" "$TARGETBUS" "$TARGET" "$LUN"
}
# -----------------------
# LED via SES (sg_ses)
# -----------------------
led_ses() {
local mode="$1" SES_DEV="$2" INDEX="$3" SLOTNUM="${4:-}"
need sg_ses
local slot_label=""
[[ -n "$SLOTNUM" ]] && slot_label=" (Slot $SLOTNUM)"
case "$mode" in
on)
sg_ses --index="$INDEX" --set=ident "$SES_DEV"
echo "LED anan${slot_label}, (SES index $INDEX via $SES_DEV)SES_DEV – $DISK"
;;
off)
sg_ses --index="$INDEX" --clear=ident "$SES_DEV"
echo "LED ausaus${slot_label}, (SES index $INDEX via $SES_DEV)SES_DEV – $DISK"
;;
blink)
sg_ses --index="$INDEX" --set=ident "$SES_DEV"
echo "LED anan${slot_label} – blinke ${BLINK_SECS}s (SES index $INDEX)…"
sleep "$BLINK_SECS"
sg_ses --index="$INDEX" --clear=ident "$SES_DEV"
echo "LED aus."
;;
esac
}
# ---------------------------------------------
# Methode wählen & LED einschalten (falls gew.)
# ---------------------------------------------
SES_DEV=""; INDEX=""; SLOTNUM=""; HOST=""; BUS=""; TARGET=""; LUN=""
OLDDEV=""
if (( USE_LED )); then
case "$METHOD" in
symlink)
led_symlink "$([[ $BLINK_SECS -gt 0 ]] && echo blink || echo on)" \
|| { echo "Symlink-LED nicht verfügbar."; exit 1; }
# H:B:T:L brauchen& wir trotzdem gleichOLDDEV fürsr delete/scan:
need lsscsi
LINE="$(lsscsi -g | awk -v d="$DISK" '{if ($(NF-1)==d) {print; exit}}')"
[[ -n "$LINE" ]] || { echo "Konnte $DISK nicht in 'lsscsi -g' finden."; exit 1; }
OLDDEV="$(awk '{print $(NF-1)}' <<<"$LINE")"
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
;;
ses)
read SES_DEV INDEX SLOTNUM HOST BUS TARGET LUN < <(get_ses_index) || exit 1
led_ses "$([[ $BLINK_SECS -gt 0 ]] && echo blink || echo on)" "$SES_DEV" "$INDEX" "$SLOTNUM"
# OLDDEV zusätzlich erfassen (nur Info)
need lsscsi
LINE="$(lsscsi -g | awk -v d="$DISK" '{if ($(NF-1)==d) {print; exit}}')"
[[ -n "$LINE" ]] && OLDDEV="$(awk '{print $(NF-1)}' <<<"$LINE")" || true
;;
auto)
if ! led_symlink "$([[ $BLINK_SECS -gt 0 ]] && echo blink || echo on)"; then
echo "(Auto) Fallback auf SES…"
read SES_DEV INDEX SLOTNUM HOST BUS TARGET LUN < <(get_ses_index) || exit 1
led_ses "$([[ $BLINK_SECS -gt 0 ]] && echo blink || echo on)" "$SES_DEV" "$INDEX" "$SLOTNUM"
else
# Symlink-Weg erfolgreich: H:B:T:L & OLDDEV besorgen
need lsscsi
LINE="$(lsscsi -g | awk -v d="$DISK" '{if ($(NF-1)==d) {print; exit}}')"
[[ -n "$LINE" ]] || { echo "Konnte $DISK nicht in 'lsscsi -g' finden."; exit 1; }
OLDDEV="$(awk '{print $(NF-1)}' <<<"$LINE")"
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
fi
;;
*) echo "Unbekannte Methode: $METHOD"; exit 1 ;;
esac
else
# Keine LED: wir brauchen nur H:B:T:L & OLDDEV
need lsscsi
LINE="$(lsscsi -g | awk -v d="$DISK" '{if ($(NF-1)==d) {print; exit}}')"
[[ -n "$LINE" ]] || { echo "Konnte $DISK nicht in 'lsscsi -g' finden."; exit 1; }
OLDDEV="$(awk '{print $(NF-1)}' <<<"$LINE")"
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
fi
# -------------
# Deregister
# -------------
echo ">>> Entferne $DISK (SCSI ${HOST}:${BUS}:${TARGET}:${LUN})"
echo 1 | sudo tee "/sys/class/scsi_device/${HOST}:${BUS}:${TARGET}:${LUN}/device/delete" >/dev/null || true
# -------------
# Prompt / Swap (ohne Slotnummer)
# -------------
if (( PROMPT )); then
read -p ">>> Bitte neue Festplatte in Slot ${TARGET} einsetzen und ENTER drücken… " _
fi
# -------------
# Rescan (gezielt für den Target-Slot)
# -------------
echo ">>> Rescanne Slot (Target ${TARGET}) über host${HOST}…"
echo "${HOST} ${BUS} ${TARGET}" | sudo tee "/sys/class/scsi_host/host${HOST}/scan" >/dev/null
# -------------
# Neues Device finden (by H:B:T:L)
# -------------
echo ">>> Warte auf neues Blockdevice im Slot (Target ${TARGET})…"
need lsscsi
NEWDISK=""
for i in {1..20}; do
NEWLINE="$(lsscsi -g | awk -v h="$HOST" -v b="$BUS" -v t="$TARGET" '$1==sprintf("[%d:%d:%d:0]",h,b,t){print; exit}')"
if [[ -n "$NEWLINE" ]]; then
NEWDISK="$(awk '{print $(NF-1)}' <<<"$NEWLINE")"
echo ">>> Neues Device: $NEWDISK ($NEWLINE)"
break
fi
sleep 1
done
if [[ -n "$NEWDISK" ]]; ||then
if [[ -n "$OLDDEV" ]]; then
if [[ "$NEWDISK" == "$OLDDEV" ]]; then
echo ">>> Hinweis: Laufwerksbuchstabe unverändert geblieben ($NEWDISK) – alles ok."
else
echo ">>> Hinweis: Buchstabe wechselte: alt=$OLDDEV neu=$NEWDISK (normal bei Hot-Swap)."
fi
fi
else
echo "Hinweis: KeinIm Zeitfenster kein neues Device innerhalbsichtbar. desEntweder Zeitfensters gesehen (ggf. Treiber/Controller langsamlangsam, /oder prüfen).der Slot wurde noch nicht neu gemeldet. Prüfe lsscsi/Logs."
fi
# -------------
# LED aus
# -------------
if (( USE_LED )); then
case "$METHOD" in
symlink)
led_symlink off || true # nutzt den gecachten locate-Pfad
;;
ses)
led_ses off "$SES_DEV" "$INDEX" "$SLOTNUM" || true
;;
auto)
if [[ -n "${SES_DEV:-}" && -n "${INDEX:-}" ]]; then
led_ses off "$SES_DEV" "$INDEX" "$SLOTNUM" || true
else
led_symlink off || true
fi
;;
esac
fi
echo ">>> Fertig."
Nun noch ausführbar machen
chmod +x /usr/local/bin/scsi-hotswap.sh
Hilfe/Benutzung:
Usage:
scsi-hotswap [--method auto|symlink|ses] [--blink N|--no-led] [--no-prompt] /dev/sdX|sdX|sdXn
Optionen:
--method M M = auto (default) | symlink | ses
--blink N LED vor dem Tausch N Sekunden blinken (statt dauerhaft an)
--no-led keine LED-Steuerung
--no-prompt nicht auf ENTER warten (setze voraus, dass neue Platte schon steckt)
Beispiele:
scsi-hotswap sdi
scsi-hotswap --method symlink --blink 8 sdg8
scsi-hotswap --method ses --no-prompt sdm
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: