Direkt zum Hauptinhalt

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: