🖥

dcheck

Storage health for server technicians — know which disk is dying before it takes the RAID with it.

SAS, SATA and NVMe SMART read natively (Dell PERC / LSI MegaRAID included), remaining-life estimates, a health gate for scripts, Prometheus metrics and webhook alerts — plus RAM, CPU and the motherboard (BIOS, devices, BMC sensors), and checks for fake or rebranded drives. One static Linux binary, no dependencies.

$ curl -fsSL https://wayang.dalang.io/dcheck/install.sh | sh

+ smartmontools (optional): … | sh -s -- --with-smartmontools

Linux & macOS · x86_64 / arm64 · latest release v0.5.1

Install guide For technicians GitHub
root@dell-r630 — sudo dcheck
dcheck device report: a 10-year-old Toshiba SAS HDD flagged MONITOR, past its design life

Real output from a Dell PowerEdge R630: a Toshiba SAS drive with 92,000 power-on hours is flagged before it fails.

What it checks

Everything a technician needs to decide: keep, watch, back up, or replace.

💾

Native SMART, no smartctl

Reads ATA, SCSI/SAS and NVMe health straight from the kernel (HDIO, SG_IO, NVMe admin). Works in a minimal rescue system. If smartmontools is installed, both sources are merged.

🖥

Built for server RAID controllers

Tested on Dell PERC H330/H730 (LSI MegaRAID 3008/3108): SAS health status, grown defects, error counters, SAS link rate and phy errors, and full SMART for SATA SSDs behind the controller (ATA pass-through, no smartctl needed).

⏳

Remaining-life estimates

SSD: vendor / ACS wear indicator or host writes vs rated TBW. HDD: power-on hours vs design life and the drive's rated start-stop / load-unload cycles. Shown for 24/7 and 8h/day, with a confidence level.

🚨

Health gate & alerts

dcheck check exits 0/1/2/3 by the worst verdict — drop it into cron, systemd or CI. dcheck watch alerts on any change for the worse and can POST a webhook.

📊

Prometheus & JSON

dcheck prometheus prints health severity, temperature, power-on hours, bytes written and more for your scraper. Every report is also available as stable JSON.

🧠

RAM & CPU too

Memory usage, ECC errors (EDAC), DIMM slot map with vendor / type / speed from SMBIOS, DDR5 temperature. CPU model, topology, clock, cache, load, and per-socket temperatures judged against each CPU's own limits.

🔍

Fake or rebranded drive?

Every SATA / SAS drive carries a WWN with its maker's IEEE OUI. dcheck checks it against the brand in the model name (all 1,662 OUIs of the major makers, from the IEEE registry), checks NVMe controller vendors (a "Samsung 980" on a Maxio controller), and flags generic names like "SSD 1TB".

🧪

Real capacity test

Counterfeit flash reports more space than it has. dcheck verify writes address-tagged data and reads it back with the OS cache dropped; a fake fails as soon as the writes pass its real capacity, and dcheck tells you the real size.

♻

Deleted a file by mistake?

dcheck recover (read-only) tells you the chance — an HDD keeps old data, an SSD with TRIM erases it — and dcheck undelete brings files back: NTFS, FAT32 and exFAT with their names, other filesystems by carving, always to another disk, with a block map of where each file lies.

🔌

Motherboard & BMC

Maker, board, BIOS version and age, UEFI / Secure Boot; PCIe devices with driver, link width and AER errors; USB devices. On servers the BMC is read over native IPMI (no ipmitool): fans, temperatures, power draw, power supplies and the event log — a redundant PSU without AC is flagged.

📟

A terminal UI that works anywhere

Neon truecolor in modern terminals, the ANSI palette on a Linux console or iDRAC/iLO virtual console, --plain for ASCII-only fonts, NO_COLOR respected, text stays selectable.

🔒

Safe by default

Reads only, unless you ask: SMART self-tests and dcheck verify. Verify writes test files to free space and deletes them, refuses to fill a system disk without --size, and overwrites a whole drive only with --destructive after you type ERASE <name>. Ceph RBD, DRBD, device-mapper and loop devices are skipped. A drive that is plugged in but never answers is still listed (from the kernel log) as REPLACE.

🔄

One binary, self-updating

~1 MB binary for Linux (static musl) and macOS, x86_64 and arm64. dcheck update downloads the latest release, verifies its SHA-256 checksum and replaces itself atomically.

Every screen

Captured on two Dell PowerEdge R630 servers and a lab PC (serial numbers masked); the counterfeit result is a simulation. Click to enlarge; arrow keys to navigate.

Install

Any Linux distribution on x86_64 or aarch64 (static binary, nothing else required), and macOS on Apple Silicon or Intel.

1. One-line install

$ curl -fsSL https://wayang.dalang.io/dcheck/install.sh | sh

Detects the architecture, downloads the release, verifies SHA-256 and installs to /usr/local/bin (with sudo if needed, or ~/.local/bin). Options: DCHECK_INSTALL_DIR=/opt/bin, DCHECK_VERSION=0.5.1 (pin a version).

2. Run it

$ sudo dcheck # terminal UI (SMART needs root) $ sudo dcheck check # one line per disk, exit code = worst verdict $ sudo dcheck storage /dev/sdb # full report for one disk $ dcheck ram && dcheck cpu # memory / processor

Offline or air-gapped server? Download the tarball for your architecture from the release directory below, copy it over, and run tar xzf + install.

3. Keep it current

$ dcheck update --check # is there a newer release? $ sudo dcheck update # download, verify SHA-256, replace in place

Optional: smartmontools as a second source

# preview first: shows the package command, changes nothing $ curl -fsSL https://wayang.dalang.io/dcheck/install.sh | sh -s -- --with-smartmontools --dry-run # install dcheck + smartmontools $ curl -fsSL https://wayang.dalang.io/dcheck/install.sh | sh -s -- --with-smartmontools

Uses apt, dnf, yum, zypper, apk, pacman or brew; skipped if already installed. Add --dry-run to see what would happen. Not required: SATA, SAS and NVMe — including SATA behind PERC/MegaRAID and USB bridges — are read natively.

Requirements

WhatNeeded?Why
Runtime librariesnoneStatic binary (musl) — any distribution, rescue systems, containers
curl / wget, sha256sum, tar, awkinstaller & updatePresent on stock Ubuntu, Debian, Fedora, RHEL. Minimal container: apt install -y curl ca-certificates
root (sudo)for SMARTRaw disk access; without it the disk list still works
smartmontoolsoptionalSecond SMART source, merged with the native read
dmidecodeoptionalRAM module detail; SMBIOS is also read directly from sysfs
curloptionalOnly for dcheck watch --webhook

Manual download

PlatformFile
Linux x86_64 (Dell / HPE / Supermicro, most PCs)dcheck-0.5.1-x86_64-unknown-linux-musl.tar.gz
Linux aarch64 (Ampere, Raspberry Pi 4/5, Orange Pi)dcheck-0.5.1-aarch64-unknown-linux-musl.tar.gz
macOS Apple Silicon (M1–M4)dcheck-0.5.1-aarch64-apple-darwin.tar.gz
macOS Inteldcheck-0.5.1-x86_64-apple-darwin.tar.gz
ChecksumsSHA256SUMS

Releases are immutable: a published version never changes. Older versions stay available under /dcheck/v<version>/.

For server technicians

From a one-off check during a site visit to continuous monitoring of a whole fleet.

Triage in five minutes

  1. Install and run sudo dcheck check — one line per disk with its verdict and the reason.
  2. Open sudo dcheck → Storage. The array table shows health, remaining life and temperature for every drive, even behind a PERC / MegaRAID controller.
  3. Enter on a flagged drive: VITALS explains why (defects, pending sectors, wear, age, cycles) and the telemetry log has every counter. Press c to copy the report into a ticket.
  4. Match the drive to a bay with the model and the last four serial digits, then plan the swap by verdict (table below).
  5. Leave monitoring behind: a timer with dcheck check, a Prometheus scrape, or dcheck watch --webhook.

What the verdicts mean

VerdictMeansDoexit
✔ OKNo failure signs.Nothing. Re-check periodically.0
? UNKNOWNNo SMART data (not root, USB bridge, SD card).Run with sudo; the report says why.1
▲ MONITOREarly warning: reallocated sectors, CRC errors, high temperature, past design life.Watch the trend, check cables and cooling, order a spare.2
✖ BACK UP NOWPending / uncorrectable sectors, media errors, attribute at threshold, wear ≥ 90%.Back up immediately, schedule the swap.3
✖ REPLACEThe drive reports SMART failure, or it is plugged in but never answers (dead drive, listed as ataN).Replace now.3

Real output — Dell R630, PERC H330

$ sudo dcheck check; echo "exit=$?" /dev/sda OK /dev/sdb MONITOR past its design life (power-on hours at 210% of rating) — plan a replacement /dev/sdc MONITOR past its design life (power-on hours at 176% of rating) — plan a replacement exit=2
$ sudo dcheck storage /dev/sdb … ▐ HEALTH Verdict : MONITOR SMART status : passed Temperature : 39°C Manufactured : 2014 week 48 — 11.8 years old In service : 91992 h powered on ≈ 10.5 y @24/7, on 89% of the time since manufacture Start-stop : 104 of 50000 rated Load-unload : 8664 of 200000 rated Written : 84.6 TB (host) Read : 4.3 PB Grown defects: 0 Uncorrected : 0 errors Design life : 43800 h (5.0 y @24/7, assumed — drives do not report it) Life used : 210% (limited by power-on hours) Life left : 0 — past its rated life by ~5.5y @24/7

Is this drive genuine?

Every disk report has an AUTHENTICITY section. Below: a generic SSD from a lab machine, and a genuine Samsung SM863a behind a PERC H730 (real output).

$ sudo dcheck storage /dev/sda … ▐ AUTHENTICITY Identity : UNBRANDED — firmware names no manufacturer WWN : 0000000000000000 ✖ WWN is all zeros — no IEEE-registered manufacturer ID ✖ model "SSD 1TB" names no manufacturer · not in smartctl's drive database Note : if the label or casing shows a brand, this drive is not what it claims
▐ AUTHENTICITY Identity : CONSISTENT — identity matches Samsung WWN : 5002538e10249cb0 ✔ WWN OUI 002538 is registered to Samsung, matching the model

Levels: CONSISTENT, UNVERIFIED (nothing to compare), UNBRANDED, SUSPICIOUS (a brand with a zero or missing WWN), LIKELY FAKE (a brand with another maker's OUI or controller). A clean result means consistent, not proven genuine — so prove the capacity too.

Prove the real capacity

In the UI: v on a disk shows the plan and asks for y before writing (free-space test only; the destructive whole-disk test stays in the shell). From a shell:

$ sudo dcheck verify /dev/sdb --size 4G … ▐ CAPACITY VERIFICATION Target : / (free space, test files) Written : 4 GiB of 4 GiB planned (608 Mbps) Read back : 4 GiB (896 Mbps) Result : PASS — all 4 GiB read back intact
# a simulated fake: reports 1 GiB, really 256 MiB (device-mapper test) ▐ CAPACITY VERIFICATION Written : 272 MiB of 1 GiB planned (1632 Mbps) Result : FAIL — 2048 of 83968 checked blocks are bad First bad : the block at 0 B held the data written for 256 MiB Real size : about 256 MiB (addresses repeat every that much) Meaning : the drive stores less than it reports — counterfeit capacity.
CommandWritesSafeguards
dcheck verify /dev/sdXTest files in free space, deleted afterwards. Existing files are kept.Asks first. On a system disk (/, /boot, /var, /home …) it needs --size or --full.
--size 8GAt most 8 GiB (quick test of the first part).—
--destructiveThe whole drive. All data on it is lost.Refused if mounted, swap or LVM/RAID. Lists the partitions and filesystems it finds; you type the device name, or ERASE <name> if it holds data.

Back up first: on a counterfeit drive, writes past its real capacity can land on existing files (dcheck stops as soon as it sees that). Verify also overwrites free space, so do not run it while you still hope to undelete a file.

Deleted a file by mistake?

Stop writing to that disk first. Then, from another shell or in the UI (u on a disk):

$ sudo dcheck recover /dev/sda # or the folder the file was in ▐ RECOVERY · /dev/sda2 Disk : /dev/sda (HDD) Filesystem : ext4 on / Chance : MEDIUM · ext4: deleting clears the block map, so names/folders are usually lost; contents can be carved · HDD: old contents stay on the platters until they are overwritten What to do: 1. Look first in: Trash, backups, snapshots. 2. Stop writing: this disk runs the system — shut down cleanly and boot a live USB. 3. Image it to ANOTHER disk: sudo ddrescue -d -n /dev/sda2 /mnt/other/sda2.img /mnt/other/sda2.map 4. Recover from the image: ext4magic … / photorec … ▐ DISK MAP · /dev/sda sda2 data in 97% of samples → ~92% of the free space still holds old data

Real output from a Dell R630 (HDD). On a lab SSD with btrfs discard=async the same command says ALMOST NONE and ~0% — TRIM had already erased the free space. Everything here is read-only; nothing is written to the disk.

Bring the files back

In the UI: on the recovery screen press d for the deleted files and their block map, space to mark, w to recover into a folder on another disk. From a shell:

$ sudo dcheck undelete /dev/sdb1 ▐ DELETED FILES Volume : whole device — FAT32, 40 MiB STATE SIZE PATH INTACT 19.5 KiB big.bin (assumed contiguous) INTACT 20 B note.txt INTACT 5.9 KiB Dokumen Kantor/Laporan Keuangan 2026.xlsx $ sudo dcheck undelete /dev/sdb1 --to /mnt/usb/rescue --match '*.xlsx' recovered /mnt/usb/rescue/Dokumen Kantor/Laporan Keuangan 2026.xlsx (5.9 KiB)
FilesystemWhat comes back
NTFSName, folder and data (fragmented files too). Deleted under Linux's ntfs3 driver the name is gone: saved as record-N with its type.
FAT32 / exFATLong name, folder and data (FAT32: assumed contiguous).
ext4 / XFS / btrfs--carve: JPEG, PNG, PDF, ZIP and Office files by signature; names are lost.

The source is only read, the destination must be on another disk, existing files are never overwritten, and each file is marked INTACT, PARTLY REUSED or OVERWRITTEN from the allocation map. Tested on images made on Linux (write, delete, write again): every recovered file matched the original's SHA-256.

Daily check with a systemd timer

# /etc/systemd/system/dcheck.service [Service] Type=oneshot ExecStart=/usr/local/bin/dcheck check # /etc/systemd/system/dcheck.timer [Timer] OnCalendar=daily Persistent=true [Install] WantedBy=timers.target

systemctl enable --now dcheck.timer. A non-zero exit marks the unit failed, so any existing alerting on failed units (or OnFailure=) picks it up.

Prometheus (node_exporter textfile)

# cron: every 15 minutes */15 * * * * root dcheck prometheus > /var/lib/node_exporter/dcheck.prom.tmp && mv /var/lib/node_exporter/dcheck.prom.tmp /var/lib/node_exporter/dcheck.prom # alert rule - alert: DiskHealthDegraded expr: dcheck_health_severity >= 2 for: 1h annotations: summary: "{{ $labels.device }} on {{ $labels.instance }} is {{ $labels.verdict }}"
# sample (Dell R630) dcheck_health_severity{device="/dev/sda",verdict="OK"} 0 dcheck_health_severity{device="/dev/sdb",verdict="MONITOR"} 2 dcheck_temperature_celsius{device="/dev/sdb"} 39 dcheck_power_on_hours{device="/dev/sdb"} 91992 dcheck_written_bytes{device="/dev/sdb"} 84573621806592

Webhook alerts (Slack, Discord, n8n, your API)

$ sudo dcheck watch --interval 3600 --webhook https://hooks.example.com/dcheck

Posts only when something gets worse (a new issue or a worse verdict):

{"event":"dcheck.alert", "alerts":["/dev/sdb worsened: OK -> MONITOR"], "devices":[{"device":"/dev/sdb","verdict":"MONITOR","severity":2, "issues":["past its design life (power-on hours at 210% of rating) — plan a replacement"], "notes":[]}]}

JSON for inventory and scripts

$ sudo dcheck storage /dev/sdb --json | jq .health { "verdict": "MONITOR", "temperature_c": 39, "power_on_hours": 91992, "manufactured": "2014-W48", "design_life_hours": 43800, "design_life_used_percent": 210, "remaining_hours": 0, "issues": ["past its design life (power-on hours at 210% of rating) — plan a replacement"], … }

Keyboard

↑ ↓ / j kMove / scrollEnterOpen
Esc / bBack1 2 3Storage / memory / processor
PgUp PgDn g GPage / top / bottomrRescan / refresh
cCopy the log (OSC 52)? / qHelp / quit

Flags: --plain (ASCII), --light, --transparent, --mouse. Env: DCHECK_COLOR=truecolor|ansi, NO_COLOR, DCHECK_NO_SPLASH. Config: ~/.config/dcheck/config.json (temp_warn_c, hdd_design_years, …).

🇮🇩 Made in Indonesia 💾 Free · MIT 🔒 Read-only — Never writes to disks 📞 +62 895-4032-00032