MacのSSD寿命診断(S.M.A.R.T.)アプリをRust×Tauriで自作|Crucial外付け対応録
長年愛用している Mac の内蔵 SSD や、Time Machine バックアップ用の外付けポータブル SSD が「今あと何 % くらい寿命が残っていて、何度で動いているのか」は、macOS 標準の「ディスクユーティリティ」をいくら眺めても「検証済み」のひと言しか出ず、具体的な消耗度までは分かりません。かといってターミナルで毎回 smartctl -a disk0 の英語の数字羅列を読むのも味気ないものです。
結論からお伝えすると、Rust 製の軽量デスクトップ基盤 『Tauri』 と smartmontools を組み合わせて 日本語版 S.M.A.R.T. 診断アプリ『smart-monitor-mac』 を AI と自作し、2 台の 27 インチ iMac と外付け SSD で実機テストを行ったことで、「通電 50,520 時間の旧 iMac で寿命が 170% と出てしまう初期値 200 仕様の罠」 と 「USB 外付け『Crucial X9 Pro For Mac』が Unknown Drive になる壁」 の両方を完全に突破できました。本記事では、Electron・Tauri・SwiftUI の実測サイズ比較から、市販の定番ソフト『DriveDx』と 1% の狂いもなく一致させた寿命計算ロジックまで包み隠さず公開します。
-
【macOS深層チューニング】APFS『スペースシェアリング』とTime Machineの構造・TCP通信調整・ATOK対ライブ変換・ブックPDF救出術 : ターミナルから
smartctlを使う基本手順と、デスクトップ Mac のスリープ・SSD 保護設計をまとめた姉妹記事です。 -
【Xcode不要でMac専用アプリ自作】Swiftを丸暗記せず『AIを社内常駐PGにする分担術』とApp Sandbox・RAMDiskビルド実践録 : Apple 純正 SwiftUI を使った軽量ネイティブ Mac アプリ自作の入門編です。
-
【実機検証】27インチ5K iMacデュアル要塞の構築録!PRO-G40 SSD 8TB×OWCハブ×Luna Displayの速度低下罠と新型Magic Trackpadが動かない原因を完全解決 : Thunderbolt 接続の超高速 SSD『PRO-G40』と USB 接続の『Crucial X9 Pro For Mac』を使い分ける実機構成です。
-
Macアクティビティモニタの不満をSwiftUI自作で解消!1画面監視&重いアプリ冬眠ツール開発録 : タブ切り替えで見づらいMac標準アクティビティモニタの不満を解消するため、CPUコア数・メモリを1画面で監視できる「CoreMonitor」とChrome等を一括冬眠(SIGSTOP)させる「MacChiller」をSwiftUIで自作した実践録です。
-
愛用の Mac(とくに長年稼働している Intel iMac 等)や 外付けポータブル SSD の「本当の残り寿命(%)と温度・総書き込み量」を日本語で見やすく管理したい 方
-
デスクトップアプリを自作する際、Electron・Tauri(Rust)・SwiftUI のどれを選ぶべきか(ファイル容量・デザイン自由度・ビルド速度の違い) を知りたい方
-
USB 接続の外付け SSD で
Device Modelが消えてUnknown Driveになったり、Apple 純正 SSD の寿命が 100% を超えて計算されたりする技術的な原因 を解決したい方
Electron・Tauri・Swiftの容量と速度比較
今回の開発では、最初に Gemini API へ直結するダークテーマのチャットアプリ(mac-chat-app)と、続いて日本語 S.M.A.R.T. 診断アプリ(smart-monitor-mac)を Rust + Web フロントエンドの『Tauri』 で構築し、その後の一連の常駐ツール群を 『SwiftUI』 で構築して両方を使い比べました。実際に Mac 上でビルドして分かった 3 大方式のリアルな違いがこちらです。
| 比較項目 | Electron(従来型Web系) | Tauri(Rust + WebKit) | SwiftUI(Apple純正ネイティブ) |
|---|---|---|---|
完成 .app の容量目安 | 約 150MB 〜 300MB 以上 | 約 5MB 〜 10MB(Universal時 15〜20MB) | 約 1MB 〜 3MB(極限まで軽量) |
| 画面描画の仕組み | Chromium ブラウザ丸ごと同梱 | macOS標準 WebKit(Safariエンジン)を間借り | macOS純正のネイティブUI部品を直接描画 |
| デザインの自由度 | ◎ HTML/CSS で自在 | ◎ CSSグラデーションやリッチな装飾が容易 | ◯ OS標準の整った表・グラフが得意 |
| 初回フルビルド時間 | 数十秒(npm パッケージ取得大) | やや長い(数百個のRustクレートを一括コンパイル) | 数秒〜十数秒(単体パッケージなら爆速) |
| RAMDisk ビルド指定 | --cache 等で個別設定 | CARGO_TARGET_DIR 環境変数で指定 | --scratch-path 引数で確実に分離 |
ほぉ〜!同じ Web デザインの画面を作るんでも、Electron だと Chrome ブラウザを丸ごと 1 個アプリの中に詰め込むけぇ 200MB 超えの巨体になるのに、Rust の Tauri なら 5〜10MB で済むんか!でもなんで Rust の最初のビルドだけは時間がかかるん?C 言語みたいに #include が多いけぇ?
いいところに気づかれましたね!厳密には C 言語の見出し宣言(#include)そのもののせいではなく、Tauri がウィンドウ制御・非同期処理(tokio)・JSON 解析(serde)など 数百個の外部ライブラリ(クレート)のソースコードを初回にまとめて厳格チェック&機械語コンパイルして 1 つの実行ファイルへ静的結合するから なんです。2 回目以降は変更した差分だけなので数秒で終わりますよ!
なお、Rust のビルド中間ファイルは数 GB に膨らむため、SSD の寿命を削らないよう .zshrc(および GUI アプリから呼ぶ場合はビルドコマンド直前)に export CARGO_TARGET_DIR="/Volumes/RAMDisk/$USER/cargo-target" を指定して 16GB RAM ディスク上へ逃がすのが鉄則です(※RAM ディスクなので Mac 再起動後の初回だけはフルビルドになりますが、SSD への書き込み摩耗は完全にゼロになります)。また --target universal-apple-darwin(または Intel 機向けの x86_64-apple-darwin)で .dmg を書き出せば、別マシンの Intel iMac へそのまま持っていって動かすことができます。
通電5万時間iMacで見抜いた寿命170%表示の罠
初期値200と閾値100から導く真の残り寿命70%
現行メイン機の iMac 20,1(2020 年モデル・NVMe 接続 Apple SSD)では、NVMe 標準の Percentage Used(使用率 %)から素直に 100 - 使用率 で残り寿命を表示できました。
ところが、書き出した .dmg をサブ機の iMac 15,1(Late 2014 モデル:通電時間 50,520 時間[丸 5.7 年相当!]・電源投入 76,534 回) へコピーして起動した瞬間、なんと画面に 「推定寿命(残り):170%」 というあり得ない数字が飛び出してきたのです。
原因を解剖して市販のプロ向け定番ソフト『DriveDx』の表示(173 Wear Leveling Count: 70% OK)と突き合わせた結果、S.M.A.R.T. の正規化値(VALUE)の「満点と寿命ライン」の奥深い仕様 が判明しました。
- 生値そのまま:VALUEの「170」をそのまま出し「残り170%」に破綻
- 100丸め:100超えを100%に丸めると「5万時間使ったのに消耗ゼロ」と誤認
- 単純割り算:新品200スタートと見て「170÷200=85%」にするとまだ甘すぎる
- Apple純正AHCI SSD(Samsung OEM等)は「開始値 200・寿命限界値(THRESH)100」
- 実際に使える有効寿命の幅は「200 − 100 = 100ポイント」
- 現在170なら30ポイント消費済み = 真の残り寿命は「(170−100)÷(200−100)=70%」
つまり、50,520 時間・76,534 回起動という過酷な年月を走り抜いてなお、有効寿命の 70% を残している(30% しか摩耗していない) という当時の Apple 純正採用 SSD の凄まじい耐久性が証明されると同時に、単純な割り算ではなく 「現在値から限界閾値(THRESH)までの残りマージン」 を計算しなければならないことが分かりました。
閾値欠落JSONの特例補正とリビジョン刻印術
さらに実機テストでもう 1 つ厄介な罠がありました。上記の閾値計算式((value - thresh) / (start - thresh))をコードに入れたのに、iMac 15,1 実機ではまだ「85%」のまま変わらなかったのです。
調べた結果、理由は 2 つ ありました。
-
smartctl -jの JSON 出力でthreshが空になる環境への特例オーバーライド : 環境やブリッジによっては、裏側の S.M.A.R.T. 出力 JSON 内でthresh(閾値)が0または欠落して返ることがあります。するとプログラムが「閾値データが無いから単純な170 ÷ 200 = 85%に戻そう」とフォールバックしていました。そこで 「Apple 製 SSD かつ正規化value > 100の属性(ID 173等)でthreshが未取得の場合は、仕様上の閾値100(開始値200)を強制適用する」 オーバーライド処理を入れたことで、確実に70%と算出されるようになりました。 -
同名
.dmgの上書きミス・キャッシュを防ぐ「リビジョン番号の常時表示」 : 2 台の Mac 間でsmart-monitor-mac.dmgを何度もやり取りしていると、ファイル名が同じせいで古いバイナリを開いてしまい「プログラムの問題なのか、古いアプリを見ているだけなのか」が切り分けられなくなります。配布ファイル名(_0.1.2_x64.dmg)だけでなく、アプリのウィンドウタイトルバー自体にも必ずv0.1.2 (Rev.3)のようにリビジョン番号を刻印する のが、個人開発で時間を溶かさない鉄則です。
外付けCrucial SSDの名前消失と寿命取得突破
Thunderbolt接続とUSB接続の決定的な壁
内蔵 SSD の次は、外付けポータブル SSD の健康診断です。ここで 「Thunderbolt 接続」と「一般的な USB 接続」の間には、macOS ドライバ上の決定的な壁 があります。
- Thunderbolt 3 / 4 接続の外付け SSD(例:『SanDisk Professional PRO-G40』): Thunderbolt は中身が PCIe バス直結(トンネリング)のため、macOS からは内蔵 NVMe SSD とまったく同じように認識され、特別な工夫なしで製品名・温度・総書き込み量・残り寿命のすべてがスッと読み取れます。
- USB 3.2 接続の外付け SSD(例:『Crucial X9 Pro For Mac』): macOS 標準の USB マスストレージドライバはセキュリティと互換性の都合上、S.M.A.R.T. コマンドの通り道に厳しい制限をかけています。また USB 変換ブリッジチップの仕様によっては完全にブロックされる機種もあります。
USB情報からの製品名補完と属性ID202の活用
実際に iMac 15,1 の Time Machine 用に繋いでいた USB ポータブル SSD 『Crucial X9 Pro For Mac(1TB)』 を自作アプリで開いてみたところ、最初は左サイドバーの名前が Unknown Drive と表示されてしまいました。
しかし生の S.M.A.R.T. テーブルを詳しく観察すると、嬉しい驚きがありました。USB 変換チップの影響で Device Model: [No Information Found] と製品名文字列だけが空欄になっていたものの、温度や寿命データ自体は USB 経由でもしっかり届いており、下部の属性 ID 202 (Percent_Lifetime_Remain) に現在の残り寿命 99(99%)が記録されていた のです!
smartctlで Device Model が空欄(Unknown)の場合は、macOSの diskutil / IOKit 側から「Crucial X9 Pro For Mac」の正式名称を補完します。
NVMeの percentage_used に加え、Crucial系(ID 202: Percent_Lifetime_Remain)やApple/Samsung系(ID 173: Wear_Leveling_Count)を優先順位付きで抽出します。
200スタート・閾値100補正を通した正確な「推定残り寿命(%)・現在温度(℃)・通電時間・電源投入回数」を1画面に描画します。
Rust バックエンドの寿命算出・製品名フォールバック関数のコアロジック(エラーハンドリング・境界値クランプ済み)は以下の通りです。
// src-tauri/src/smart_parser.rs(抜粋:NVMe・Crucial ID 202・Apple OEM 200開始/閾値100対応)
use serde::Serialize;
#[derive(Serialize, Clone, Debug)]
pub struct DiskHealthSummary {
pub device_node: String,
pub model_name: String,
pub temperature_c: Option<i64>,
pub power_on_hours: Option<u64>,
pub power_cycles: Option<u64>,
pub remaining_life_pct: Option<u8>,
}
/// ATA S.M.A.R.T. 属性リストからメーカー別の残り寿命(%)を安全に算出
pub fn calc_ata_remaining_life(attrs: &[(u32, String, i64, Option<i64>)], is_apple_ssd: bool) -> Option<u8> {
// 優先探索対象: 202 (Crucial等 Percent_Lifetime_Remain), 173 (Apple/Samsung Wear_Leveling_Count),
// 177 (Wear_Leveling_Count), 231 (SSD_Life_Left), 233 (Media_Wearout_Indicator)
let target_ids = [202_u32, 173, 177, 231, 233];
for tid in target_ids {
if let Some((_, _, val, raw_thresh)) = attrs.iter().find(|(id, _, _, _)| *id == tid) {
if *val <= 0 {
return Some(0);
}
// Apple純正AHCI SSD等で開始値が200(現在値が100超え)かつJSON上のthreshが0/欠落している場合の特例補正
if *val > 100 || (is_apple_ssd && tid == 173) {
let start = 200_i64;
let thresh = match raw_thresh {
Some(t) if *t > 0 && *t < start => *t,
_ => 100_i64,
};
let span = (start - thresh).max(1);
let pct = ((*val - thresh) * 100) / span;
return Some(pct.clamp(0, 100) as u8);
}
// 通常の100満点開始属性(Crucial ID 202 = 99 など)
if let Some(t) = raw_thresh {
if *t > 0 && *t < 100 {
let span = (100 - *t).max(1);
let pct = ((*val - *t) * 100) / span;
return Some(pct.clamp(0, 100) as u8);
}
}
return Some((*val).clamp(0, 100) as u8);
}
}
None
}
この改良を入れた結果、iMac 20,1 の内蔵 NVMe、iMac 15,1 の 5 万時間稼働 SSD(70%)、そして USB 接続の『Crucial X9 Pro For Mac』(製品名も正しく表示され残り寿命 99%)のすべてが一目で診断できるようになりました。
『Unknown Drive』って出てた迷子の外付け SSD さんに、ちゃんと本当のお名前と「寿命 99% 元気でち!」っていう健康診断書がついたでちね!
はい!なお他社PCへアプリを配る場合は、受け入れ側にも brew install smartmontools が入っていることと、個人ビルドの未署名 .app は初回のみ Control キーを押しながらクリックして「開く」 を選ぶ点を覚えておくとスムーズですよ!
まとめ:愛機と外付けSSDの健康を数値で見守る
SSD はハードディスクのように異音の前兆を出さず、寿命が尽きると突然リードオンリーや認識不能になる記憶装置です。「RAM ディスクで日々の無駄な書き込み摩耗を防ぎつつ、自作の S.M.A.R.T. モニターで内蔵 SSD とバックアップ用外付け SSD の『真の残り寿命(%)と温度』を定期的にチェックする」——この習慣があれば、5 万時間を超えるベテラン Mac でも安心してデータを守り抜けます。
ご自身の Mac でも軽量な日本語 S.M.A.R.T. 診断ダッシュボードを自作してみたい方は、以下のコピペ用プロンプトをご活用ください(事前準備として brew install smartmontools のみ実行しておいてください)。
※メーカーごとに異なる S.M.A.R.T. 属性 ID や diskutil 製品名補完、境界値クランプを正確に実装させるため、必ず 『Gemini 4 Argon』(または同等以上の最上位推論モデル)を選択して実行してください。
以下の記事の設計を参考に、macOS上で内蔵SSDおよび外付けSSDの健康状態を日本語で一覧表示する軽量デスクトップアプリ『SmartMonitorMac』を作成してください(Tauri v2[Rust]またはSwiftUIのどちらでも私の環境に合う方を事前確認して提案してください)。
参照URL: https://lab.chihouzakki.com/blog/review/rust-tauri-smart-ssd-health-monitor-crucial-imac-diy/
【実装ルールと安全要件(厳守)】
1. 物理ディスク一覧(/dev/disk0, /dev/disk1 ...)を自動検出し、選択したディスクについて `/opt/homebrew/sbin/smartctl` または `/usr/local/sbin/smartctl`(`-j -a`)を実行して「モデル名」「健康ステータス」「現在温度(℃)」「総書き込み量(TBW換算)」「通電時間」「電源投入回数」「推定残り寿命(%)」を美しいダークテーマの日本語パネルで表示してください(smartctl未導入時は分かりやすい導入案内を表示しクラッシュさせないこと)。
2. USB接続の外付けSSD(Crucial X9 Pro For Mac等)で smartctl 側の model_name が空欄や Unknown になる場合に備え、`diskutil info -plist` の MediaName / VolumeName から正式な製品名を自動補完してください。
3. 残り寿命(%)の算出は、NVMeの `percentage_used`(100 - used)に加え、ATA属性の ID 202(Crucial等 Percent_Lifetime_Remain)、ID 173 / 177(Apple/Samsung等 Wear_Leveling_Count)、ID 231 / 233 に対応し、特にApple純正AHCI SSDのように正規化値が100を超える(200開始・閾値100)個体では `(value - thresh) / (200 - thresh)`(thresh欠落時は100を適用)でDriveDxと同等の正確な残り寿命(0〜100%にクランプ)を算出してください。
4. ウィンドウのタイトルバーに必ずアプリのリビジョン番号(例: v0.1.2)を表示し、ビルド中間生成物はSSDを摩耗させないよう RAMDisk(Rustなら CARGO_TARGET_DIR=/Volumes/RAMDisk/$USER/cargo-target、Swiftなら --scratch-path /Volumes/RAMDisk/$USER/swift-build/...、未マウント時は /tmp)へ出力してください。 大切なデータと愛機のストレージ寿命を賢く見守って、安心・快適な Mac ライフを続けていきましょう!

▲ 5万時間走ったベテランSSDも外付けSSDも、健康診断でバッチリ安心!