#!/usr/bin/env bash
# 独立服务器硬盘信息查看脚本
# 用法：sudo bash disk-info.sh

set -u

if [[ "${EUID}" -ne 0 ]]; then
  echo "请使用 root 运行：sudo bash $0"
  exit 1
fi

command_exists() { command -v "$1" >/dev/null 2>&1; }

section() {
  printf '\n\033[1;36m===== %s =====\033[0m\n' "$1"
}

human_bytes() {
  numfmt --to=iec --suffix=B "$1" 2>/dev/null || echo "${1}B"
}

section "系统"
echo "主机名：$(hostname)"
echo "时间：$(date '+%F %T %Z')"
echo "内核：$(uname -sr)"
echo "架构：$(uname -m)"

section "块设备与分区"
if command_exists lsblk; then
  lsblk -e 7 -o NAME,PATH,MODEL,SERIAL,TYPE,SIZE,ROTA,TRAN,FSTYPE,LABEL,MOUNTPOINTS
else
  echo "未找到 lsblk"
fi

section "文件系统使用情况"
df -hT -x tmpfs -x devtmpfs -x squashfs 2>/dev/null || df -hT

section "磁盘 inode 使用情况"
df -ih -x tmpfs -x devtmpfs -x squashfs 2>/dev/null || true

section "内核识别的磁盘"
for dev in /sys/block/*; do
  [[ -e "$dev/device" || -e "$dev/queue" ]] || continue
  name="$(basename "$dev")"
  [[ "$name" == loop* || "$name" == ram* || "$name" == fd* ]] && continue
  size_sectors=$(cat "$dev/size" 2>/dev/null || echo 0)
  echo "设备：/dev/$name"
  echo "  容量：$(human_bytes $((size_sectors * 512)))"
  echo "  只读：$(cat "$dev/ro" 2>/dev/null || echo '?')"
  echo "  旋转盘：$(cat "$dev/queue/rotational" 2>/dev/null || echo '?')"
  echo "  调度器：$(cat "$dev/queue/scheduler" 2>/dev/null || echo '?')"
done

section "SSD 总读取/写入量（SMART 生命周期统计）"
if ! command_exists smartctl; then
  echo "未安装 smartctl。需要时执行：apt update && apt install -y smartmontools"
else
  smart_seen=0
  while read -r disk type; do
    [[ -z "$disk" ]] && continue
    echo "--- $disk ---"
    smart_text=$(smartctl -A "$disk" 2>/dev/null || true)
    read_lba=$(awk '$0 ~ /Total_LBAs_Read/ {print $NF; exit}' <<< "$smart_text")
    write_lba=$(awk '$0 ~ /Total_LBAs_Written/ {print $NF; exit}' <<< "$smart_text")
    if [[ "$read_lba" =~ ^[0-9]+$ || "$write_lba" =~ ^[0-9]+$ ]]; then
      smart_seen=1
      if [[ "$read_lba" =~ ^[0-9]+$ ]]; then
        read_bytes=$((read_lba * 512))
        echo "总读取：$(numfmt --to=iec --suffix=B "$read_bytes" 2>/dev/null || echo "${read_bytes}B")（${read_lba} 个 LBA）"
      else
        echo "总读取：SMART 未提供"
      fi
      if [[ "$write_lba" =~ ^[0-9]+$ ]]; then
        write_bytes=$((write_lba * 512))
        echo "总写入：$(numfmt --to=iec --suffix=B "$write_bytes" 2>/dev/null || echo "${write_bytes}B")（${write_lba} 个 LBA）"
      else
        echo "总写入：SMART 未提供"
      fi
    else
      echo "SMART 未提供 Total_LBAs_Read / Total_LBAs_Written"
    fi
  done < <(lsblk -dn -o PATH,TYPE 2>/dev/null | awk '$2=="disk" {print $1, "disk"}')
  [[ "$smart_seen" -eq 0 ]] && echo "提示：部分云盘、RAID 或虚拟磁盘不会提供硬盘生命周期读写量。"
fi

section "磁盘健康信息（SMART）"
if ! command_exists smartctl; then
  echo "未安装 smartctl。需要时执行：apt update && apt install -y smartmontools"
else
  while read -r disk type; do
    [[ -z "$disk" ]] && continue
    echo
    echo "--- $disk ($type) ---"
    smartctl -H "$disk" 2>&1 | sed -n '1,18p'
    smartctl -A "$disk" 2>/dev/null | grep -Ei 'temperature|percentage|media|error|unsafe|critical|wear|power.on|reallocated|pending|uncorrect' | head -30 || true
  done < <(lsblk -dn -o PATH,TYPE 2>/dev/null | awk '$2=="disk" {print $1, "disk"}')
fi

section "磁盘累计读写量"
echo "统计自系统启动以来的累计值（不是实时速度）："
printf "%-12s %18s %18s %18s %18s\\n" "设备" "读取量" "写入量" "读取次数" "写入次数"
while read -r major minor name reads merged_reads sectors_read time_read writes merged_writes sectors_written time_write rest; do
  [[ "$name" == loop* || "$name" == ram* || "$name" == sr* || "$name" == dm-* || "$name" == zd* || "$name" == md* ]] && continue
  [[ "$name" =~ ^[a-zA-Z] ]] || continue
  read_bytes=$((sectors_read * 512))
  write_bytes=$((sectors_written * 512))
  read_human=$(numfmt --to=iec --suffix=B "$read_bytes" 2>/dev/null || echo "${read_bytes}B")
  write_human=$(numfmt --to=iec --suffix=B "$write_bytes" 2>/dev/null || echo "${write_bytes}B")
  printf "%-12s %18s %18s %18s %18s\\n" "/dev/$name" "$read_human" "$write_human" "$reads" "$writes"
done < /proc/diskstats

echo "提示：这是内核自启动以来的累计读写量；重启后通常会重新累计。"

section "磁盘实时读写"
if command_exists iostat; then
  echo "采样 2 秒（第一行是启动以来平均值，第二行是当前采样）："
  iostat -dxm 1 2 2>/dev/null | awk '
    /^Device/ {n++; print; next}
    /^[a-zA-Z][a-zA-Z0-9._-]*[[:space:]]/ && $1 !~ /^(loop|ram|sr|dm-|zd|md)/ {print}
  '
else
  echo "未安装 iostat。安装：apt update && apt install -y sysstat"
  echo "当前内核累计计数（读取/写入次数与扇区数）："
  printf "%-12s %14s %14s %18s %18s\\n" "设备" "读取次数" "写入次数" "读取扇区" "写入扇区"
  while read -r name _ reads _ sectors_read _ _ writes _ sectors_written rest; do
    [[ "$name" == loop* || "$name" == ram* || "$name" == sr* || "$name" == dm-* ]] && continue
    printf "%-12s %14s %14s %18s %18s\\n" "/dev/$name" "$reads" "$writes" "$sectors_read" "$sectors_written"
  done < /proc/diskstats
fi

section "磁盘 I/O 错误（最近日志）"
if command_exists journalctl; then
  journalctl -k -b 0 --no-pager 2>/dev/null | grep -Ei 'I/O error|blk_update|buffer I/O|medium error|critical medium|nvme.*error|ata.*error|reset.*link' | tail -30 || echo "未发现明显磁盘 I/O 错误"
else
  dmesg -T 2>/dev/null | grep -Ei 'I/O error|blk_update|buffer I/O|medium error|critical medium|nvme.*error|ata.*error|reset.*link' | tail -30 || echo "未发现明显磁盘 I/O 错误"
fi

section "结论提示"
echo "ROTA=0 通常表示 SSD/NVMe，ROTA=1 通常表示机械硬盘。"
echo "SMART 健康状态只能作为参考；云服务器/虚拟机可能无法读取真实物理硬盘 SMART。"
echo "如发现 Reallocated/Pending/Uncorrectable、Critical Warning 或大量 I/O error，应立即备份并联系服务商。"
