Расширенные возможности оболочки и инструменты

Рейтинг: 71.7% · 16 голосов
Полный курс по Android Debug Bridge: установка, подключение, shell, логи, dumpsys, автоматизация, root, беспроводная отладка. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
android_roman
Сообщения: 45
Зарегистрирован: 11 май 2026, 05:31

Расширенные возможности оболочки и инструменты

Сообщение android_roman »

АкадемияADB: Android Debug BridgeГлава 28 из 29
Оглавление курса (29)
  1. Введение в Android Debug Bridge
  2. Установка и настройка рабочей среды
  3. Подключение устройства (проводное и беспроводное)
  4. Базовые команды ADB и управление сервером
  5. Команды состояния и перезагрузки
  6. Навигация по файловой системе
  7. Управление пакетами приложений
  8. Логирование с помощью logcat
  9. Системные дампы и диагностика (dumpsys)
  10. Анализ производительности в реальном времени
  11. Эмуляция ввода (input)
  12. Управление Activity и Intent (am)
  13. Работа с оконным менеджером (wm)
  14. Захват экрана и запись видео
  15. Root-доступ и его применение
  16. Модификация системных настроек через settings
  17. Команды для поставщиков контента (content)
  18. Резервное копирование и восстановление (backup)
  19. Проброс портов и туннелирование
  20. Беспроводная отладка (Wi-Fi)
  21. Взаимодействие с эмуляторами
  22. Написание скриптов на Bash/CMD/PowerShell
  23. ADB в языках программирования
  24. Автоматизация тестирования с ADB
  25. Безопасность и лучшие практики
  26. ADB на Android TV, Wear OS и IoT
  27. Восстановление и низкоуровневые операции
  28. Расширенные возможности оболочки и инструменты (вы здесь)
  29. Отладка самого ADB и устранение неполадок
В главах 4 и 6 вы работали с adb shell как с обычным терминалом, а в главе 7 ставили и удаляли пакеты. Эта глава про то, что лежит уровнем глубже: какой набор утилит на самом деле живет внутри Android и как его расширить, как запускать фоновые процессы, переживающие отключение кабеля, и как командой cmd дергать системные сервисы напрямую, от шторки уведомлений до радиомодуля.

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 ...
Точная версия зависит от прошивки: на Android 14 обычно 0.8.9, на Android 15 свежее. Большинство файлов в /system/bin это симлинки на один бинарь toybox:

Код: Выделить всё

$ adb shell ls -l /system/bin/ls
lrwxr-xr-x 1 root shell 6 2025-11-02 12:00 /system/bin/ls -> toybox
Практическое следствие: ключи урезаны относительно GNU-версий. toybox sed не знает часть расширений GNU sed, у grep нет -P (perl-регулярки), у find нет -printf. awk на устройстве есть, но это классический one-true-awk, а не gawk. Если скрипт из главы 22 падает с Unknown option, первым делом проверяйте, не GNU-специфичный ли это флаг.

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.
Вызов апплета выглядит как /data/local/tmp/busybox vi file.txt. Чтобы не писать путь каждый раз, разверните симлинки и поправьте PATH в рамках сессии:

Код: Выделить всё

$ 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
Частые грабли. Первое: залили бинарь в /sdcard и ловите Permission denied при запуске. Раздел /sdcard смонтирован с noexec, исполнять оттуда нельзя в принципе, chmod не поможет, только /data/local/tmp. Второе: сборка не той архитектуры, симптом Exec format error или внезапный Syntax error. Для aarch64 берите armv8l. Третье: на Android 10+ приложениям запрещено исполнять бинарники из своих домашних каталогов, но к adb shell (uid shell) и /data/local/tmp это ограничение не относится. Для постоянной установки в систему нужен root, обычно это модуль Magisk (глава 15).

pm и cmd package:

Сюрприз для многих: pm на современном Android это не бинарь, а крошечный шелл-скрипт.

Код: Выделить всё

$ adb shell cat /system/bin/pm
#!/system/bin/sh
cmd package "$@"
То же самое с am (обертка над cmd activity) и wm (cmd window). Команда cmd обращается к системному сервису напрямую через binder, без запуска отдельной Java-VM, как делали старые версии pm. Поэтому на Android 7 pm заметно тормозил, а сейчас отвечает мгновенно. Список сервисов, доступных через cmd:

Код: Выделить всё

$ adb shell cmd -l
Currently running services:
  ...
  notification
  package
  phone
  statusbar
  window
  ...
Рабочий минимум сверх того, что было в главе 7:

Код: Выделить всё

# где лежит 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
Типичная ошибка pm grant:

Код: Выделить всё

$ 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
Причина одна из двух: разрешение не объявлено в манифесте приложения, либо это не runtime-разрешение (pm grant работает только с уровнем dangerous, на install-time разрешения он ругается, что тип неизменяемый).

Демоны и фоновые задачи:

Внутри одной сессии фоновый запуск делается амперсандом. Проблема начинается при закрытии сессии: процесс получает SIGHUP и умирает вместе с ней. Если сборщик логов должен пережить отключение кабеля, нужен nohup, и обязательно перенаправьте все три потока:

Код: Выделить всё

$ adb shell "nohup logcat -f /data/local/tmp/boot.log -r 16384 -n 8 >/dev/null 2>&1 </dev/null &"
Без перенаправления stdout и stderr команда adb shell зависнет: она ждет закрытия потоков, которые держит фоновый процесс. Это самые частые грабли, выглядит как "adb завис", хотя процесс давно работает. Альтернатива, отвязка от терминала через setsid (он есть в toybox):

Код: Выделить всё

$ 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
Обратите внимание на PPID, равный 1: процесс переехал под init и больше не зависит от adb. Ограничения честные: все умирает при перезагрузке, автозапуск без root не сделать (с root это init-скрипты или service.d у Magisk). Фантомный киллер из Android 12, который режет дочерние процессы приложений вроде Termux по лимиту в 32 штуки, процессы от adb shell не трогает, у них uid shell, а не приложения.

cmd statusbar, cmd notification и телефония:

Через cmd доступны сервисы, до которых раньше добирались только через UI. Шторка:

Код: Выделить всё

$ adb shell cmd statusbar expand-notifications   # раскрыть шторку
$ adb shell cmd statusbar expand-settings        # раскрыть быстрые настройки
$ adb shell cmd statusbar collapse               # свернуть
В автотестах из главы 24 collapse перед скриншотом надежнее, чем слать KEYCODE_BACK через input. Еще statusbar управляет плитками быстрых настроек, компонент TileService указывается полностью, пакет/класс:

Код: Выделить всё

$ 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
cmd notification умеет постить уведомления прямо из шелла, без всякого приложения:

Код: Выделить всё

$ 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)
Уведомление приходит от пакета com.android.shell, тег build1 позволяет потом обновить его повторным post. Удобный сигнальный механизм для скриптов: долгий прогон закончился, на устройстве всплыло уведомление. Тем же сервисом включают слушателей уведомлений и доступ к DND без похода по настройкам:

Код: Выделить всё

$ adb shell cmd notification allow_listener com.example.app/.MyListenerService
$ adb shell cmd notification allow_dnd com.example.app
С телефонией главная ловушка в имени сервиса. Службы telephony не существует, сервис называется phone:

Код: Выделить всё

$ adb shell cmd telephony
cmd: Can't find service: telephony

$ adb shell cmd phone data disable   # выключить мобильные данные
$ adb shell cmd phone data enable    # включить обратно
Проверить результат можно через settings get global mobile_data (глава 16), вернется 0 или 1. Старый эквивалент svc data disable пока жив, а вот svc wifi на свежих версиях объявлен устаревшим и ничего не делает, вместо него cmd wifi set-wifi-enabled disabled. Из менее повседневного, cmd phone читает carrier config, чем удобно проверять, что оператор разрешил VoLTE:

Код: Выделить всё

$ adb shell cmd phone cc get-value carrier_volte_available_bool
carrier_volte_available_bool : true
Полный список подкоманд любого сервиса смотрите через help: cmd phone help, cmd notification help, cmd statusbar help. Набор отличается между версиями Android и прошивками: на устройствах Xiaomi или Huawei части подкоманд может не быть, а отдельные команды требуют userdebug-сборки и на обычном устройстве вернут SecurityException. Это нормально, ориентируйтесь на вывод help конкретного устройства.

Что дальше:

В финальной главе 29 разберем отладку самого adb: device offline, unauthorized, конфликты нескольких серверов и чтение логов adb-демона.
👍1 ❤️2 🔥2 😄 🤔1
✔ Лучший ответ сформирован автоматически — yura98
Подтверждаю грабли с редиректами. У нас на CI скрипт стартовал logcat в фоне и adb shell висел до таймаута джобы, два дня грешили на usb-хаб. Вопрос: /dev/null 2>&1, без stdin.
Перейти к ответу →
Аватара пользователя
yura98
Сообщения: 2
Зарегистрирован: 08 июн 2026, 16:00
Репутация: 101

Re: Расширенные возможности оболочки и инструменты

Сообщение yura98 »

✔ Лучший ответ — сформирован автоматически
Подтверждаю грабли с редиректами. У нас на CI скрипт стартовал logcat в фоне и adb shell висел до таймаута джобы, два дня грешили на usb-хаб. Вопрос: </dev/null правда обязателен? у меня вроде отвисло уже после того как добавил >/dev/null 2>&1, без stdin.
👍1 ❤️2 🔥1 😄 🤔
Пишу код, который потом сам не понимаю.
Аватара пользователя
renpro6
Сообщения: 1
Зарегистрирован: 21 май 2026, 22:32

Re: Расширенные возможности оболочки и инструменты

Сообщение renpro6 »

android_roman писал(а):Раздел /sdcard смонтирован с noexec, исполнять оттуда нельзя в принципе, chmod не поможет
а с root можно перемонтировать /sdcard с exec или там еще FUSE-эмуляция мешает? или проще не страдать и жить в /data/local/tmp как в уроке?
👍 ❤️ 🔥 😄 🤔
Аватара пользователя
juniorgrind
Сообщения: 2
Зарегистрирован: 18 май 2026, 12:12

Re: Расширенные возможности оболочки и инструменты

Сообщение juniorgrind »

android_roman писал(а):Альтернатива, отвязка от терминала через setsid
так а практическая разница в чем? оба варианта переживают разрыв сессии. setsid нужен только если процесс сам лезет к управляющему терминалу, или есть еще кейсы где nohup не спасет?
👍1 ❤️ 🔥 😄 🤔
Аватара пользователя
willbill
Сообщения: 1
Зарегистрирован: 26 май 2026, 11:21

Re: Расширенные возможности оболочки и инструменты

Сообщение willbill »

pm disable-user это лучшее что случалось с моим redmi, вырубил analytics и msa, реклама из шторки пропала. одно но: после крупного обновления MIUI часть пакетов включается обратно, держу скрипт со списком и прогоняю после каждой прошивки.
👍 ❤️ 🔥2 😄 🤔
Ответить
← Предыдущая глава
Восстановление и низкоуровневые операции
Следующая глава →
Отладка самого ADB и устранение неполадок

Все главы курса «ADB: Android Debug Bridge»

Поделиться темой: ✈ Telegram VK

Вернуться в «ADB: Android Debug Bridge»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость