Toybox, штатный набор команд Android:
Когда вы набираете ls или grep в adb shell, работает не GNU coreutils, а Toybox, компактная реализация Unix-утилит под лицензией 0BSD. Google использует ее с Android 6.0 вместо старого Toolbox. Проверка версии и списка доступных апплетов:
Код: Выделить всё
$ adb shell toybox --version
toybox 0.8.10-android
$ adb shell toybox
acpi base64 basename blkdiscard blockdev cal cat chattr chcon chgrp chmod
chown chroot chrt cksum clear cmp comm cp cpio cut date dd df diff dirname
dmesg dos2unix du echo egrep env expand expr fallocate false fgrep file ...
Код: Выделить всё
$ adb shell ls -l /system/bin/ls
lrwxr-xr-x 1 root shell 6 2025-11-02 12:00 /system/bin/ls -> toybox
Busybox, когда штатного не хватает:
Busybox это сторонний комбайн утилит в одном бинаре. Ставить его в /system без root нельзя, но для отладочных задач и не нужно: статическая сборка спокойно работает из /data/local/tmp. Сначала узнайте архитектуру, потом залейте подходящий бинарь (статические сборки есть на busybox.net в разделе downloads/binaries, или соберите сами):
Код: Выделить всё
$ adb shell uname -m
aarch64
$ adb push busybox-armv8l /data/local/tmp/busybox
$ adb shell chmod 755 /data/local/tmp/busybox
$ adb shell /data/local/tmp/busybox | head -2
BusyBox v1.35.0 (2022-05-26 22:53:30 UTC) multi-call binary.
BusyBox is copyrighted by many authors between 1998-2015.
Код: Выделить всё
$ adb shell
blackshark:/ $ mkdir -p /data/local/tmp/bin
blackshark:/ $ /data/local/tmp/busybox --install -s /data/local/tmp/bin
blackshark:/ $ export PATH=/data/local/tmp/bin:$PATH
blackshark:/ $ which vi
/data/local/tmp/bin/vi
pm и cmd package:
Сюрприз для многих: pm на современном Android это не бинарь, а крошечный шелл-скрипт.
Код: Выделить всё
$ adb shell cat /system/bin/pm
#!/system/bin/sh
cmd package "$@"
Код: Выделить всё
$ adb shell cmd -l
Currently running services:
...
notification
package
phone
statusbar
window
...
Код: Выделить всё
# где лежит apk пакета
$ adb shell pm path com.android.chrome
package:/data/app/~~3kQzR9w==/com.android.chrome-9fGhB2A==/base.apk
# выдать и отозвать runtime-разрешение
$ adb shell pm grant com.example.app android.permission.ACCESS_FINE_LOCATION
$ adb shell pm revoke com.example.app android.permission.ACCESS_FINE_LOCATION
# отключить предустановленный пакет без root (классика для прошивок Xiaomi)
$ adb shell pm disable-user --user 0 com.miui.analytics
Package com.miui.analytics new state: disabled-user
$ adb shell pm enable com.miui.analytics
# удалить пакет только для пользователя 0 и потом восстановить
$ adb shell pm uninstall -k --user 0 com.facebook.appmanager
Success
$ adb shell cmd package install-existing com.facebook.appmanager
Package com.facebook.appmanager installed for user: 0
# принудительная AOT-компиляция (полезно перед замерами из главы 10)
$ adb shell pm compile -m speed -f com.example.app
Success
Код: Выделить всё
$ adb shell pm grant com.example.app android.permission.CAMERA
Exception occurred while executing 'grant':
java.lang.SecurityException: Package com.example.app has not requested
permission android.permission.CAMERA
Демоны и фоновые задачи:
Внутри одной сессии фоновый запуск делается амперсандом. Проблема начинается при закрытии сессии: процесс получает SIGHUP и умирает вместе с ней. Если сборщик логов должен пережить отключение кабеля, нужен nohup, и обязательно перенаправьте все три потока:
Код: Выделить всё
$ adb shell "nohup logcat -f /data/local/tmp/boot.log -r 16384 -n 8 >/dev/null 2>&1 </dev/null &"
Код: Выделить всё
$ adb shell "setsid sh -c 'while true; do date >> /data/local/tmp/tick.log; sleep 60; done' >/dev/null 2>&1 </dev/null &"
Код: Выделить всё
$ adb shell ps -A | grep logcat
shell 14233 1 10916164 3804 do_sys_poll 0 S logcat
$ adb shell pkill logcat
cmd statusbar, cmd notification и телефония:
Через cmd доступны сервисы, до которых раньше добирались только через UI. Шторка:
Код: Выделить всё
$ adb shell cmd statusbar expand-notifications # раскрыть шторку
$ adb shell cmd statusbar expand-settings # раскрыть быстрые настройки
$ adb shell cmd statusbar collapse # свернуть
Код: Выделить всё
$ adb shell cmd statusbar add-tile com.example.app/.MyTileService
$ adb shell cmd statusbar click-tile com.example.app/.MyTileService
$ adb shell cmd statusbar remove-tile com.example.app/.MyTileService
Код: Выделить всё
$ adb shell cmd notification post -S bigtext -t "CI" build1 "Сборка 2143 прошла, apk в артефактах"
posting:
Notification(channel=shellcmd pri=0 contentView=null vibrate=null sound=null
defaults=0x0 flags=0x0 color=0x00000000 vis=PRIVATE)
Код: Выделить всё
$ adb shell cmd notification allow_listener com.example.app/.MyListenerService
$ adb shell cmd notification allow_dnd com.example.app
Код: Выделить всё
$ adb shell cmd telephony
cmd: Can't find service: telephony
$ adb shell cmd phone data disable # выключить мобильные данные
$ adb shell cmd phone data enable # включить обратно
Код: Выделить всё
$ adb shell cmd phone cc get-value carrier_volte_available_bool
carrier_volte_available_bool : true
Что дальше:
В финальной главе 29 разберем отладку самого adb: device offline, unauthorized, конфликты нескольких серверов и чтение логов adb-демона.