はじめに
以前、NVMe SSDのS.M.A.R.T.ログデータを取得するPowershellスクリプトを紹介しました。
NVMeではS.M.A.R.T.ログデータの基本項目とその取得方法が仕様書に定義されていて、かつWindows標準デバイスドライバの使いかたを説明したドキュメントも整備されていたおかげで、スクリプトの作成は比較的楽でした。
ただ私が業務でかかわる中ではまだSATA SSDも多く、「SATA SSDのS.M.A.R.T.データ(属性)を取得するPowershellスクリプトも作成できるはず」と考えて試しました。この記事はその顛末をまとめたものです。
なお、作成したスクリプトはGithubに置いてあります[1]。コードの全体はそちらを参照してください。
まとめ
- Windowsもストレージドライブの情報取得用コマンドレットを提供している
- このスクリプトの方法はそれらコマンドレットでは機能が不十分であるときに使うべき
- ATA Passthroughという機能を利用するとSATAドライブからSMART情報を取得できる
有用なコマンドレットも数多くある
私が作成したスクリプトではWindowsにおけるioctl()
に相当するDeviceIoControl()
を呼び出すという力づくの方法を使用しています。しかもSATAドライブ専用です。
こんな方法を使わなくても良いように、Windowsはストレージの情報取得用コマンドレットを数多く提供しています。まずはこれらのコマンドレットの一部を紹介します。もしこれらのコマンドレットで目的が達成できるのであればこちらを使うべきです。こちらであればSATAとNVMeどちらのSSDでも共通に扱えます。
それらコマンドレットの一覧はMicrosoftのWebページに掲載されています(リンク先はWindows Server 2025とWindows 11のPowerShell用)。「こんなものがあるのか」と新鮮な発見があります。
S.M.A.R.T.のようないわゆるヘルスリポートに近い情報を取得するものはGet-StorageReliabilityCounter
コマンドレットのようです。使用例は以下のとおりです。FriendlyName
オプションに渡している名前は私の環境のものです。この名前はGet-PhysicalDisk
コマンドレットを引数なしで実行すると取得できます。
PS C:\> Get-PhysicalDisk -FriendlyName "WDC WDS250G2B0A-00SM50" | Get-StorageReliabilityCounter | Format-List
上記コマンドレットの使用結果例を示します。なお実行には管理者権限が必要です。
実行結果例
まずGet-PhysicalDisk
コマンドレットを引数なしで実行し、対象ドライブのFriendlyName
を取得します。
PS C:\> Get-PhysicalDisk
Number FriendlyName SerialNumber MediaType CanPool OperationalStatus HealthStatus Usage Size
------ ------------ ------------ --------- ------- ----------------- ------------ ----- ----
0 WDC WDS240G2G0B-00EPW0 190704803011 SSD False OK Healthy Auto-Select 223.58 GB
1 WDC WDS250G2B0A-00SM50 183777800517 SSD False OK Healthy Auto-Select 232.89 GB
この"Healthy"という出力で十分であれば、このコマンドレットだけで良いですね。
ここでは1番のドライブの情報を取得します。ヘルスリポートを取得する前にドライブの基本情報を取得します。
PS C:\> Get-PhysicalDisk -FriendlyName "WDC WDS250G2B0A-00SM50" | Format-List
ObjectId : (省略)
PassThroughClass :
PassThroughIds :
PassThroughNamespace :
PassThroughServer :
UniqueId : (省略)
Description :
FriendlyName : WDC WDS250G2B0A-00SM50
HealthStatus : Healthy
Manufacturer :
Model : WDC WDS250G2B0A-00SM50
OperationalDetails :
OperationalStatus : OK
PhysicalLocation : Integrated : Bus 0 : Device 23 : Function 0 : Adapter 0 : Port 1
SerialNumber : (省略)
AdapterSerialNumber :
AllocatedSize : 250058301440
BusType : SATA
CannotPoolReason : Insufficient Capacity
CanPool : False
DeviceId : 1
EnclosureNumber :
FirmwareVersion : X61190WD
IsIndicationEnabled :
IsPartial : True
LogicalSectorSize : 512
MediaType : SSD
OtherCannotPoolReasonDescription :
PartNumber :
PhysicalSectorSize : 512
Size : 250059350016
SlotNumber :
SoftwareVersion :
SpindleSpeed : 0
StoragePoolUniqueId :
SupportedUsages : {Auto-Select, Manual-Select, Hot Spare, Retired...}
UniqueIdFormat : FCPH Name
Usage : Auto-Select
VirtualDiskFootprint : 0
PSComputerName :
ClassName : MSFT_PhysicalDisk
項目BusType
にこのSSDがSATAドライブであると表示されています。
そこで実際にヘルスレポートを取得します。
PS C:\> Get-PhysicalDisk -FriendlyName "WDC WDS250G2B0A-00SM50" | Get-StorageReliabilityCounter | Format-List
ObjectId : (省略)
PassThroughClass :
PassThroughIds :
PassThroughNamespace :
PassThroughServer :
UniqueId : (省略)
DeviceId : 1
FlushLatencyMax : 482
LoadUnloadCycleCount :
LoadUnloadCycleCountMax :
ManufactureDate :
PowerOnHours : 4145
ReadErrorsCorrected : 0
ReadErrorsTotal : 0
ReadErrorsUncorrected :
ReadLatencyMax : 3088
StartStopCycleCount :
StartStopCycleCountMax :
Temperature : 33
TemperatureMax : 0
Wear : 0
WriteErrorsCorrected :
WriteErrorsTotal :
WriteErrorsUncorrected :
WriteLatencyMax : 1551
PSComputerName :
結果を見ると、電源投入時間(PowerOnHours)やReadやWriteのエラー回数などが報告されています。"Wear"という項目の値がNANDの疲弊度を表現しているかどうかは不明です。
直接SATA SSDのS.M.A.R.T.データを取得する
NVMe SSDを操作したときはWindows標準のNVMeドライバを使用してNVMeコマンド(Get Log Page
コマンド)を発行しました。これに対して今回は、ATA Passthroughという仕組みを使用してATAコマンドを発行します。
S.M.A.R.T.情報を取得するATAコマンドはSMART READ DATA
コマンドであり、指定するパラメータは図1のとおりです[2]。
図1の仕様にしたがい以下のようにS.M.A.R.T情報を取得するATAコマンドを組み立て、DeviceIoControl()
にはATA Passthroughを指定してコマンドを発行します。
$CMDDescriptor.CurrTF0 = 0xD0; # Features
$CMDDescriptor.CurrTF1 = 0; # Counts
$CMDDescriptor.CurrTF2 = 0; # LBA Low
$CMDDescriptor.CurrTF3 = 0x4F; # LBA Mid
$CMDDescriptor.CurrTF4 = 0xC2; # LBA High
$CMDDescriptor.CurrTF5 = 0; # Device
$CMDDescriptor.CurrTF6 = 0xB0; # SMART READ DATA (28bit command)
$CMDDescriptor.CurrTF7 = 0;
$ByteRet = 0;
$IoControlCode = 0x0004D02C; # IOCTL_ATA_PASS_THROUGH
コマンドが成功すると、ドライブから512バイトのデータが転送され、指定したバッファに格納されます。
取得したデータを解釈する
取得したデータ(512バイト)の先頭2バイトにはバージョン番号が格納されていて、その後ろに30個の属性データが格納されます。
各属性データのサイズは12バイトで、先頭から順に属性のID(1バイト)、フラグ(2バイト)、現在値(1バイト)、ベンダ固有フィールド(8バイト)です[3]。
ただ「ベンダ固有フィールド」の先頭1バイトは最悪値として使われることが多いため[4]、このスクリプトでもそのように解釈しています。また、ベンダ固有フィールドのうち4バイトのみを「生の値」として表示しています。
スクリプトでは、受領した512バイトの先頭からバージョン番号が格納されている2バイト分ずらした位置を基準に、12バイトずつループを回して属性データを解釈しています。属性全体のサイズは360バイト(=12バイト x 30個)であり属性データが格納されている位置はバイト2からバイト361までとなりますので、ループの終了条件もそれに合わせて設定します。
$Position = 2;
do {
$Id = [Int][System.Runtime.InteropServices.Marshal]::ReadByte( $OutBuffer, $Offset + $Position + 0 );
$IdStr = $Id.ToString().PadLeft(3);
$Flags = [Int][System.Runtime.InteropServices.Marshal]::ReadByte( $OutBuffer, $Offset + $Position + 1 );
$Flags += ([Int][System.Runtime.InteropServices.Marshal]::ReadByte( $OutBuffer, $Offset + $Position + 2 ) -shl 8 );
$FlagsStr = $Flags.ToString("X2");
$Curr = [Int][System.Runtime.InteropServices.Marshal]::ReadByte( $OutBuffer, $Offset + $Position + 3 );
$CurrStr = $Curr.ToString().PadLeft(3);
(snip)
$Position += 12;
} while( $Position -lt 362 )
実行結果の例が図2です。
同じSATA SSDに対してCrystalDiskInfoを使用してS.M.A.R.T.データを取得した結果が図3です。
図3:同じSATA SSDのS.M.A.R.T.データをCrystalDiskInfoで取得した結果
このように、作成したスクリプトでもCrystalDiskInfoと同じ値(現在値と最悪値)を取得できていることがわかります。
なお、図3には"Threshold"(閾値)という値が表示されています。この値は属性値を取得するコマンドとは別のコマンドを使用して取得する必要があり、今回作成したスクリプトには実装していません。
また、図2の実行結果に表示されている「フラグ」のビット0とビット1にはそれぞれ意味があるのですが、その解釈と表示もしていません。それらはこのスクリプトを少し改造すれば対応できますので、もし興味があれば試してみてください。
さらに、図2では図3に表示されている"Attribute Name"(属性名)を表示していません。これは以前説明したとおりSATA SSDのS.M.A.R.T.属性の内容(項目)はあくまでベンダ固有のものであり仕様化(共通化)されていないからです。ベンダー(メーカー)がIDと項目名の一覧を公開している場合もありますが、複数メーカー間で同じIDでも内容が異なることも多いです。このため正確な属性名とデータの対応を取得するには対象SSDのS.M.A.R.T.データ仕様を入手する必要があります。
おわりに
この記事では、PowerShellスクリプトだけでSATA SSDのS.M.A.R.T.データを取得する方法について、作成したスクリプトを紹介しながら説明しました。また、Windowsが提供している情報取得用コマンドレットの一部も紹介しました。
日常使用するPCに搭載されたドライブの情報取得や監視であればGUI付きのツールなどが有用です。一方で、多数のドライブや稼働中はアクセスしにくいドライブ、そしてサードパーティー製アプリケーションを導入できない環境での管理では、軽量でかつ結果の加工やカスタマイズが容易でWindowsの標準機能のみで実現可能な情報取得方法が求められることもあります。今回紹介した方法を使えばそのような条件下でもSSDの情報取得が可能です。
References
[1] Kenichiro Yoshii, "satatool-win-powershell: Sample script for accessing SATA drive via ATA Pass-Through with powershell in Windows"
[2] T13, "Information technology - ATA/ATAPI Command Set - 3 (ACS-3)," Working draft, Revision 5, October, 2013
[3] "Self-Monitoring, Analysis and Reporting Technology (S.M.A.R.T.)," SFF-8035i, Revision 2.0, April, 1996
[4] Wikipedia, "Self-Monitoring, Analysis and Reporting Technology," Retrieved on June 4, 2025
ライセンス表記
この記事はクリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンスの下に提供されています。