Unyablog.

のにれんのブログ

Android の df コマンドについて

最近 Android 用の mackerel-agent を作ろうとしていて、Android/proc/meminfo を読んだりしていたのですが、 filesystem の metrics は df -P コマンドを使っていました。*1

Android にも df コマンドは存在していたのでパースしようとしたのですが、バージョンごとの違いなどがあったのでメモ。

バージョンによる挙動

Andorid 6.0.1 (Marshmallow) まで

$ adb shell
shell@SO-02H:/ $ df
Filesystem               Size     Used     Free   Blksize
/dev                   889.4M   104.0K   889.3M   4096
/sys/fs/cgroup         889.4M     0.0K   889.4M   4096
/sys/fs/cgroup/memory: Permission denied
/mnt                   889.4M     0.0K   889.4M   4096
/tmp                   889.4M     4.0K   889.4M   4096
/system                  4.9G     3.9G     1.1G   4096
/data                   21.9G    12.1G     9.8G   4096
/oem                   503.7M   340.1M   163.6M   4096
/cache                 341.0M   304.0K   340.7M   4096
/rca                     8.4M     6.4M     1.9M   1024
/idd                    14.0M     4.9M     9.0M   1024
/persist                27.5M   804.0K    26.7M   4096
/firmware               80.0M    56.5M    23.5M   16384
/lta-label              11.7M     1.1M    10.6M   4096
/storage               889.4M     0.0K   889.4M   4096
/mnt/runtime/default/emulated: Permission denied
/storage/emulated       21.9G    12.1G     9.8G   4096
/mnt/runtime/read/emulated: Permission denied
/mnt/runtime/write/emulated: Permission denied

Android 6.0 までの df コマンドは coreutilsdf とは大きく異なります。

マウントされた先しか見ることが出来ない他、 -h などのオプションは一切使えません。

$ adb shell
shell@SO-02H:/ $ df -h
Filesystem               Size     Used     Free   Blksize
-h: No such file or directory

Android 7.0 (Nougat) 以降? *2

$ adb shell
bullhead:/ $ df
Filesystem                                             1K-blocks     Used Available Use% Mounted on
tmpfs                                                     922680      428    922252   1% /dev
tmpfs                                                     922680        0    922680   0% /mnt
/dev/block/dm-0                                          2999516  2430552    552580  82% /system
/dev/block/dm-1                                           241908   184160     52752  78% /vendor
/dev/block/platform/soc.0/f9824900.sdhci/by-name/cache     92656     4504     86188   5% /cache
/dev/block/platform/soc.0/f9824900.sdhci/by-name/modem     88016    56720     31296  65% /firmware
/dev/block/dm-2                                         26094648 12222956  13855308  47% /data
/dev/fuse                                               26094648 12222956  13855308  47% /storage/emulated

Android 7.0 では coreutils と同じ形式になりました。

-h-P などのオプションも使えるようになり便利。

$ adb shell
bullhead:/ $ df -h
Filesystem                                             Size  Used Avail Use% Mounted on
tmpfs                                                  901M  428K  901M   1% /dev
tmpfs                                                  901M     0  901M   0% /mnt
/dev/block/dm-0                                        2.8G  2.3G  540M  82% /system
/dev/block/dm-1                                        236M  180M   52M  78% /vendor
/dev/block/platform/soc.0/f9824900.sdhci/by-name/cache  90M  4.3M   84M   5% /cache
/dev/block/platform/soc.0/f9824900.sdhci/by-name/modem  86M   55M   31M  65% /firmware
tmpfs                                                  901M     0  901M   0% /storage
/dev/block/dm-2                                         25G   12G   13G  47% /data
/dev/fuse                                               25G   12G   13G  47% /storage/emulated

細かい話

  • Android 6.0 までの実装は以下にあり、Android toolbox に含まれていました。/proc/mounts から読み取っていますが特にオプションを受け取るなどは行っていません。

platform_system_core/df.c at marshmallow-release · android/platform_system_core · GitHub

  • Android 7.0 からは df の実装が toybox に置き換わったので、POSIX に準拠するようになりました。

Lose df to toybox. · android/platform_system_core@cca6019 · GitHub

toybox とは linux コマンド群の BSD ライセンス実装です*3

おまけ

toybox 自体は 6.0 から Android に取り込まれているので、toybox を使えば 6.0 でも新しい df を使えました。

$ adb shell
shell@SO-02H:/ $ toybox df
Filesystem      1K-blocks       Used  Available Use% Mounted on
tmpfs              910748        104     910644   1% /dev
none               910748          0     910748   0% /sys/fs/cgroup
tmpfs              910748          0     910748   0% /mnt
tmpfs              910748          4     910744   1% /tmp
/dev/block/dm-0   5174428    4054116    1103928  79% /system
/dev/block/bootdevice/by-name/userdata 22994780   12698312   10280084  56% /data
/dev/block/bootdevice/by-name/oem 515776     348284     156844  69% /oem
/dev/block/bootdevice/by-name/cache 349136        304     341624   1% /cache
/dev/block/bootdevice/by-name/diag 14327       5165       8835  37% /idd
/dev/block/bootdevice/by-name/persist 28144        804      26688   3% /persist
/dev/block/bootdevice/by-name/modem 81872      57824      24048  71% /firmware
/dev/block/bootdevice/by-name/LTALabel 12016       1168      10524  10% /lta-label
/dev/fuse        22994780   12698312   10280084  56% /storage/emulated

ただ、toybox のバージョンが少し古いので長い filesystem に対応できずはみ出しています。*4

ということで、今回は Android 6.0 以前と Android 7.0 以降でパースを分けるという対応になりそうです。toybox のおかげで色々コマンド打てるようになって便利。

*1:https://github.com/mackerelio/mackerel-agent/blob/master/util/filesystem.go

*2:未来のことはわからない

*3:busybox は GPL2 なので Android のライセンス上含められなかったそう

*4:ここで修正されている https://github.com/landley/toybox/commit/c10638d3b16d065c1efd97ae17c1a8bf417be706