こんにちは、 STORES でコーポレートエンジニアをしている佐々木です。
コーポレートエンジニア が所属する IT 本部は、人事や労務といったいわゆるバックオフィスの部署と同じ PX 本部の中にあります。
PX は People Experience の略で、プロダクト開発がユーザー体験を重視するように、 STORES で働いている人は自分たちにとってのユーザーであるという考え方を表しています。
私が所属する IT本部 コーポレートエンジニアリンググループは、デバイス管理、オフィスネットワーク、SaaSの活用、社内ツールの開発など、全社横断的な課題をエンジニアリングで改善する事を目標にしています。
ノート PC のバッテリー不調に早めに気付きたい
お仕事でノート PC を利用することは多いと思うのですが、ノート PC の宿命としてバッテリーの不調によるトラブルは割と多いのではないかと思っています。
使い方や個体差によって修理推奨が出る時期はバラつくためユーザーが気づかないうちにバッテリーが劣化していることも多いですが、管理者側でバッテリーの状態を把握できることでPCの不調に早めに気づいたり、交換の声掛けを早めに行うなどの対処も可能になります。
STORES では MacBook Pro/Air を利用 している割合が高く、デバイス管理に Jamf Pro を使っています。
Jamf Pro のコンピュータインベントリには Battery Capacity (バッテリー容量)という項目があるのですが、これは Intel CPU が搭載された機種のみ対応しており、Apple Silicon 搭載の機種では誤った値が返ってきていました。
Jamf Pro の拡張属性という機能を使うことでデバイスの状態を定期的に取得してインベントリに表示することができるため、その機能を使って Mac のバッテリー状態をモニタリングする方法について書いていこうと思います。
前提
最近 Jamf Pro の 11.11.0 がリリースされ 、コンピュータインベントリに Battery Health (バッテリーヘルス)という項目が追加されました。
これはバッテリーの充電可能容量ではなく 、macOS のシステム設定やシステム情報で確認できるバッテリーの正常性を確認できる項目と同じ情報になります。
Jamf Pro リリースノート 11.11.0 | learn.jamf.com
*11月27日現在、検証環境の 11.11.2 では正しく機能しているが、本番環境の 11.11.1 ではunknown
と表示されている。
Apple Silicon 搭載の macOS 14.4 以降のデバイスのみがサポート対象の機能ですが、Intel Mac が今後増えることはなく、また OS もアップデートを行う事を考えると、今回の記事の内容がそのまま役に立つケースは無いかもしれません。
ただ今回取り上げる system_profiler
や plutil
、 plutil
を使って情報を取得する方法は他にも応用できるかなと思い、記事の最後の方でも例をあげています。
Mac のバッテリー状態の確認方法
前述の通り、MacBookはバッテリーの性能が低下すると修理推奨の表示が出ます。これは主にバッテリーの充電可能容量が設計された最大容量の80%を下回っている場合に表示されます。
macOS のシステム設定やシステム情報など、GUI 上でバッテリーの状態を確認することができますが、 Jamf Pro の拡張属性として値を取得するためには スクリプト として実行する必要があります。
バッテリーの状態
system_profiler
コマンドで取得することができます。
system_profiler SPPowerDataType
を実行すると、中に Health Information
という項目があります。
以下の例は Health Information
以外を省略しています。
・Apple Silicon 搭載 バッテリー正常
Health Information: Cycle Count: 88 Condition: Normal Maximum Capacity: 83%
・Intel 搭載 バッテリー修理推奨
Health Information: Cycle Count: 745 Condition: Service Recommended
バッテリーが修理推奨のステータスの場合、Condition
が Service Recommended
になります。
また、Apple Silicon と Intel で表示される内容に差異があり、Health Information
の場合は Apple Silicon のデバイスのみ Maximum Capacity
がリストされます。
現在の最大バッテリー容量
前述の通り system_profiler
で取得した情報の中にある Maximum Capacity
という値は Apple Silicon 搭載の MacBook でのみ取得可能です。
Jamf Pro のコンピュータインベントリ内の Hardware に Battery Capacity (バッテリー容量)という項目もあるのですが、こちらも前述の通り Intel Mac では正しく表示されているものの、Apple Silicon だと誤った値になっています。
状態さえ取れていれば現在の最大バッテリー容量を取る必要性は低いですが、Jamf Pro のスマートコンピュータグループで Intel と Apple Silicon で 同じ値を参照したり、Apple Silicon でもバッテリー容量が 80% を切るよりも前に気付けるというメリットがあります。
Apple Silicon の場合はバッテリーの状態を取得したときに Maximum Capacity
が取れているので例は割愛します。
Intelの場合は割とめんどうで、 ioreg
コマンドを使って 現在の最大容量と設計時の最大容量を取得し、その値から計算しました。各オプションについてはここでは割愛します。
ioreg -rlc AppleSmartBattery -w 0
の実行結果から、MaxCapacity
(またはAppleRawMaxCapacity
)とDesignCapacity
を探します
"MaxCapacity" = 3424 "AppleRawMaxCapacity" = 3424 "DesignCapacity" = 5088
3424 / 5088 * 100 = 67.2955974843
ということで、Jamf Pro で表示されている数値とほぼ一致しました。
Apple Silicon だと MaxCapacity
が 100 となっていたり、 AppleRawMaxCapacity
で計算しても system_profiler
や GUI 上で確認した値と少しずれているため今回は使いません。
また、 AppleRaw〜
という key は他にもあるのですがこれはあとから追加されたもので、CPU アーキテクチャや OS のバージョンによって使えない事があるため使わなかったと記憶しています。
PermanentFailureStatus
充電できず、電源アダプタを抜くと即落ちるみたいな状態の Mac でシステム情報を見ると表示されていることがあります。今まで 1000 台以上 の Mac を管理してきましたが、2台だけ見たことがあります。
状況から考えてバッテリーのコントローラーが壊れたとかそういうときに出てるようです。非常に稀なので気にしなくても良いかもしれません。
Intel Mac のバッテリー容量を計算したときと同じioreg -rlc AppleSmartBattery -w 0
の実行結果から、 PermanentFailureStatus
の項目を確認します。
"PermanentFailureStatus" = 0
この値は bool
で返ってくるはずなのですが、私が見たケースは整数が返ってきていました(4096とか)。
余談:当時 Apple Open Source で該当しそうな部分(AppleSmartBattery.cpp)を読んでみたのですが、バッテリーから返ってきた値をそのまま出してそうな雰囲気でした。 最近のもの を見たらだいぶ変わっていたので今は挙動が違うかもしれません(ちゃんと読んでないです)。
コマンドの結果を扱いやすくする
system_profiler
や ioreg
はオプションで JSON や XML で出力できます。
どちらもmacOSに標準で入っている plutil
で扱えるため、IT 管理者がリモートから実行するスクリプトとして使いやすく、grep
や awk
などを使うより読みやすくなると思います。
system_profiler
system_profiler
は オプションをつけることで XML(plist) や JSON で出力することができます。
今回は JSON で出力してみました。結果は省略しています。
system_profiler SPPowerDataType -json
・ Apple Silicon
{ "SPPowerDataType" : [ { "sppower_battery_health_info" : { "sppower_battery_cycle_count" : 88, "sppower_battery_health" : "Good", "sppower_battery_health_maximum_capacity" : "83%" } } ] }
・ Intel バッテリー修理推奨
{ "SPPowerDataType" : [ { "sppower_battery_health_info" : { "sppower_battery_cycle_count" : 745, "sppower_battery_health" : "Check Battery", } } ] }
JSON や XML で出力すると、key や value の表記が変わります。
例えばバッテリーの状態はオプションをつけない場合は項目が Condition
、 値が Normal
や Service Recommended
でしたが、JSON や XML の場合は key がsppower_battery_health
, value がGood
や Check Battery
のようになっています。
ioreg
ioreg
は -a
オプションをつけることで XML(plist)で出力することができます。
結果は省略しています。
ioreg -arlc AppleSmartBattery -w 0
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <array> <dict> <key>DesignCapacity</key> <integer>5088</integer> <key>MaxCapacity</key> <integer>3424</integer> <key>PermanentFailureStatus</key> <integer>0</integer> </dict> </array> </plist>
plutil で目的の値を取得する
JSON や XML で出力した結果と目的の key のパスを plutil
に渡すことで value を取得します。
plutil
はオプションに -
をつけることで標準入力を受け取ります。
・ system_profiler
% system_profiler SPPowerDataType -json | plutil -extract SPPowerDataType.0.sppower_battery_health_info.sppower_battery_health raw - Good
・ ioreg
% ioreg -arlc AppleSmartBattery -w 0 | plutil -extract 0.PermanentFailureStatus raw - 0
Jamf Pro に拡張属性として追加する
拡張属性に登録するシェルスクリプトの例になります。
Jamf Pro の拡張属性についてはドキュメントをご参照下さい。
バッテリーの状態
PermanentFailureStatus
が 0
のときはバッテリーの状態のみを、それ以外のときはPermanentFailureStatus
とバッテリーの状態を両方表示するようにしています。
permanentFailureStatus=$(ioreg -arlc AppleSmartBattery -w 0 | plutil -extract 0.PermanentFailureStatus raw - ) batteryHealth=$(system_profiler SPPowerDataType -json | plutil -extract SPPowerDataType.0.sppower_battery_health_info.sppower_battery_health raw - ) if [[ $permanentFailureStatus != "0" ]]; then result="Battery Permanent Failure, Code: ${permanentFailureStatus}\nBattery Health: ${batteryHealth}" else result="$batteryHealth" fi echo "<result>$result</result>"
バッテリーの最大容量
CPU によって処理を変えています。
拡張属性の Data Type を Integer
にすることでスマートコンピュータグループなどで (例えば値が85未満のデバイスをリストするなど) 扱いやすくなります。
ただ、拡張属性の Data Type が Integer
でも、%
がついたままだと String
として扱われてしまうため、Apple Silicon の場合は %
を削除しています。
arch=$(/usr/bin/arch) if [[ "$arch" == "arm64" ]]; then result=$(system_profiler SPPowerDataType -json | plutil -extract SPPowerDataType.0.sppower_battery_health_info.sppower_battery_health_maximum_capacity raw - | tr -d '%' ) elif [[ "$arch" == "i386" ]]; then resutlsBatteryInfo=$(ioreg -arlc AppleSmartBattery -w 0) maxCapacity=$(plutil -extract 0.MaxCapacity raw - <<< $resutlsBatteryInfo) designCapacity=$(plutil -extract 0.DesignCapacity raw - <<< $resutlsBatteryInfo) result=$(echo "scale=2; $maxCapacity/$designCapacity*100" | bc | awk '{printf("%d\n",$1)}') fi echo "<result>$result</result>"
デスクトップマシンの場合はバッテリーの情報が無くエラーになるため、環境にデスクトップマシンがある場合はモデル名を取得して条件分岐するなど考慮が必要です。
モデルを取得する方法は以下のような例があります。
% system_profiler SPHardwareDataType -json | plutil -extract SPHardwareDataType.0.machine_model raw - MacBookPro18,4
表示例
スマートコンピュータグループを作成する
作成した拡張属性を使用してスマートコンピュータグループを作成できます。
スマートコンピュータグループを作成することで、 Jamf Pro ダッシュボードに表示したり、グループに変更があったらメールで通知したりできます。
Jamf Pro のスマートコンピュータグループについてはドキュメントをご参照下さい。
learn.jamf.com
バッテリーの状態
正常な場合は値が Good
になっているので、それ以外の場合を指定します。
バッテリーの最大容量
結果を Integer
で返しているため、クライテリアに不等号が使えます。例は 85 未満をリストする場合です。
バッテリー以外の情報を取得する例
先ほど Mac のモデルを取得する例を出しましたが、他にもplutil
を使うことでシンプルに書くことができます。
デバイスやアプリケーションの設定や情報などを取得する例をいくつかあげてみます。
MacBook のキーボードレイアウトを取得する
iogeg
コマンドを使って、 MacBook のキーボードレイアウトを取得するコマンドをシンプルに書くことができます。
・ JIS の結果
% ioreg -arln AppleHIDKeyboardEventDriverV2 | plutil -extract 0.KeyboardLanguage raw - Japanese Keyboard
・ US の結果
% ioreg -arln AppleHIDKeyboardEventDriverV2 | plutil -extract 0.KeyboardLanguage raw - U.S.
plist の値を参照する
plist が存在する場合、 plutil
を使用して設定値や状態などを確認することができます。
例として Google Chrome のバージョンを見てみます。
% plutil -extract KSVersion raw /Applications/Google\ Chrome.app/Contents/Info.plist 131.0.6778.86
Web API のレスポンスを扱う
シェルスクリプトで Web API のレスポンスを扱う場合にも plutil
が便利なケースがあります。
例として Google Chrome の VersionHistory API から macOS 版の最新バージョンを取得してみます。
% curl -s https://versionhistory.googleapis.com/v1/chrome/platforms/mac/channels/stable/versions | plutil -extract versions.0.version raw - 131.0.6778.86
まとめ
- Jamf Pro の拡張属性を使うことで、管理者が Mac の状態や組織で必要な設定について把握しやすくなる
- macOS の場合 plist を参照することが多いので、
plutil
を使うことで読みやすくシンプルに書くことができるケースがある
ちょっと長くなってしまいましたが、この記事がどなたかのお役に立つことがあれば幸いです。
宣伝:社内IT分野のソフトウェアエンジニアを募集しています
STORES のコーポレートエンジニアは自分たちの日々の仕事はもちろん、全社での業務への AI 活用を進めるため、ソフトウェア開発ができる仲間を探しています。
今回の内容は AI と関係無いのですが、根幹にはユーザーの体験を良くしてより良い環境を作っていきたいという思いがあり、これは STORES が掲げる "Just for Fun" というミッションにも繋がっています。
私達のお仕事に興味を持ってくださった方がいらっしゃいましたら、ジョブディスクリプションのページをご覧いただければと思います。