Поиск…


Вступление

ADB (Android Debug Bridge) - это инструмент командной строки, который используется для связи с экземпляром эмулятора или подключенным устройством Android.

Обзор АБР

Большая часть этой темы была разделена на adb shell

замечания

Список примеров, перенесенных в оболочку adb :

Печать подробного списка подключенных устройств

Чтобы получить подробный список всех устройств, подключенных к adb , введите в свой терминал следующую команду:

adb devices -l

Пример вывода

List of devices attached
ZX1G425DC6             device usb:336592896X product:shamu model:Nexus_6 device:shamu
013e4e127e59a868       device usb:337641472X product:bullhead model:Nexus_5X device:bullhead
ZX1D229KCN             device usb:335592811X product:titan_retde model:XT1068 device:titan_umtsds
A50PL                  device usb:331592812X
  • Первый столбец - это серийный номер устройства. Если он начинается с emulator- , это устройство является эмулятором.
  • usb: путь устройства в подсистеме USB.
  • product: код продукта устройства. Это очень специфично для конкретного производителя, и, как вы можете видеть в случае устройства Archos A50PL выше, оно может быть пустым.
  • model: модель устройства. Как product , может быть пустым.
  • device: код устройства. Это также очень специфично для производителя и может быть пустым.

Чтение информации об устройстве

Напишите в терминале следующую команду:

adb shell getprop

Это напечатает всю доступную информацию в виде пар ключ / значение.

Вы можете просто прочитать определенную информацию, добавив имя конкретного ключа в команду. Например:

adb shell getprop ro.product.model

Вот несколько интересных фрагментов информации, которые вы получаете:

  • ro.product.model : Название модели устройства (например, Nexus 6P)
  • ro.build.version.sdk : Уровень API устройства (например, 23)
  • ro.product.brand : Брендинг устройства (например, Samsung)

Полный вывод примера

[dalvik.vm.dex2oat-Xms]: [64m]
[dalvik.vm.dex2oat-Xmx]: [512m]
[dalvik.vm.heapsize]: [384m]
[dalvik.vm.image-dex2oat-Xms]: [64m]
[dalvik.vm.image-dex2oat-Xmx]: [64m]
[dalvik.vm.isa.x86.variant]: [dalvik.vm.isa.x86.features=default]
[dalvik.vm.isa.x86_64.features]: [default]
[dalvik.vm.isa.x86_64.variant]: [x86_64]
[dalvik.vm.lockprof.threshold]: [500]
[dalvik.vm.stack-trace-file]: [/data/anr/traces.txt]
[debug.atrace.tags.enableflags]: [0]
[debug.force_rtl]: [0]
[dev.bootcomplete]: [1]
[gsm.current.phone-type]: [1]
[gsm.defaultpdpcontext.active]: [true]
[gsm.network.type]: [UMTS]
[gsm.nitz.time]: [1469106902492]
[gsm.operator.alpha]: [Android]
[gsm.operator.iso-country]: [us]
[gsm.operator.isroaming]: [false]
[gsm.operator.numeric]: [310260]
[gsm.sim.operator.alpha]: [Android]
[gsm.sim.operator.iso-country]: [us]
[gsm.sim.operator.numeric]: [310260]
[gsm.sim.state]: [READY]
[gsm.version.ril-impl]: [android reference-ril 1.0]
[init.svc.adbd]: [running]
[init.svc.bootanim]: [stopped]
[init.svc.console]: [running]
[init.svc.debuggerd]: [running]
[init.svc.debuggerd64]: [running]
[init.svc.drm]: [running]
[init.svc.fingerprintd]: [running]
[init.svc.gatekeeperd]: [running]
[init.svc.goldfish-logcat]: [stopped]
[init.svc.goldfish-setup]: [stopped]
[init.svc.healthd]: [running]
[init.svc.installd]: [running]
[init.svc.keystore]: [running]
[init.svc.lmkd]: [running]
[init.svc.logd]: [running]
[init.svc.logd-reinit]: [stopped]
[init.svc.media]: [running]
[init.svc.netd]: [running]
[init.svc.perfprofd]: [running]
[init.svc.qemu-props]: [stopped]
[init.svc.ril-daemon]: [running]
[init.svc.servicemanager]: [running]
[init.svc.surfaceflinger]: [running]
[init.svc.ueventd]: [running]
[init.svc.vold]: [running]
[init.svc.zygote]: [running]
[init.svc.zygote_secondary]: [running]
[net.bt.name]: [Android]
[net.change]: [net.dns2]
[net.dns1]: [10.0.2.3]
[net.dns2]: [10.0.2.4]
[net.eth0.dns1]: [10.0.2.3]
[net.eth0.dns2]: [10.0.2.4]
[net.eth0.gw]: [10.0.2.2]
[net.gprs.local-ip]: [10.0.2.15]
[net.hostname]: [android-5e1af924d72dc578]
[net.qtaguid_enabled]: [1]
[net.tcp.default_init_rwnd]: [60]
[persist.sys.dalvik.vm.lib.2]: [libart.so]
[persist.sys.profiler_ms]: [0]
[persist.sys.timezone]: [Europe/Vienna]
[persist.sys.usb.config]: [adb]
[qemu.gles]: [1]
[qemu.hw.mainkeys]: [0]
[qemu.sf.fake_camera]: [none]
[qemu.sf.lcd_density]: [560]
[rild.libargs]: [-d /dev/ttyS0]
[rild.libpath]: [/system/lib/libreference-ril.so]
[ro.allow.mock.location]: [0]
[ro.baseband]: [unknown]
[ro.board.platform]: []
[ro.boot.hardware]: [ranchu]
[ro.bootimage.build.date]: [Thu Jul 7 15:56:30 UTC 2016]
[ro.bootimage.build.date.utc]: [1467906990]
[ro.bootimage.build.fingerprint]: [Android/sdk_google_phone_x86_64/generic_x86_64:6.0/MASTER/3038907:userdebug/test-keys]
[ro.bootloader]: [unknown]
[ro.bootmode]: [unknown]
[ro.build.characteristics]: [emulator]
[ro.build.date]: [Thu Jul  7 15:55:30 UTC 2016]
[ro.build.date.utc]: [1467906930]
[ro.build.description]: [sdk_google_phone_x86_64-userdebug 6.0 MASTER 3038907 test-keys]
[ro.build.display.id]: [sdk_google_phone_x86_64-userdebug 6.0 MASTER 3038907 test-keys]
[ro.build.fingerprint]: [Android/sdk_google_phone_x86_64/generic_x86_64:6.0/MASTER/3038907:userdebug/test-keys]
[ro.build.flavor]: [sdk_google_phone_x86_64-userdebug]
[ro.build.host]: [vpak15.mtv.corp.google.com]
[ro.build.id]: [MASTER]
[ro.build.product]: [generic_x86_64]
[ro.build.tags]: [test-keys]
[ro.build.type]: [userdebug]
[ro.build.user]: [android-build]
[ro.build.version.all_codenames]: [REL]
[ro.build.version.base_os]: []
[ro.build.version.codename]: [REL]
[ro.build.version.incremental]: [3038907]
[ro.build.version.preview_sdk]: [0]
[ro.build.version.release]: [6.0]
[ro.build.version.sdk]: [23]
[ro.build.version.security_patch]: [2015-10-01]
[ro.com.google.locationfeatures]: [1]
[ro.config.alarm_alert]: [Alarm_Classic.ogg]
[ro.config.nocheckin]: [yes]
[ro.config.notification_sound]: [OnTheHunt.ogg]
[ro.crypto.state]: [unencrypted]
[ro.dalvik.vm.native.bridge]: [0]
[ro.debuggable]: [1]
[ro.hardware]: [ranchu]
[ro.hardware.audio.primary]: [goldfish]
[ro.kernel.android.checkjni]: [1]
[ro.kernel.android.qemud]: [1]
[ro.kernel.androidboot.hardware]: [ranchu]
[ro.kernel.clocksource]: [pit]
[ro.kernel.console]: [0]
[ro.kernel.ndns]: [2]
[ro.kernel.qemu]: [1]
[ro.kernel.qemu.gles]: [1]
[ro.opengles.version]: [131072]
[ro.product.board]: []
[ro.product.brand]: [Android]
[ro.product.cpu.abi]: [x86_64]
[ro.product.cpu.abilist]: [x86_64,x86]
[ro.product.cpu.abilist32]: [x86]
[ro.product.cpu.abilist64]: [x86_64]
[ro.product.device]: [generic_x86_64]
[ro.product.locale]: [en-US]
[ro.product.manufacturer]: [unknown]
[ro.product.model]: [Android SDK built for x86_64]
[ro.product.name]: [sdk_google_phone_x86_64]
[ro.radio.use-ppp]: [no]
[ro.revision]: [0]
[ro.runtime.firstboot]: [1469106908722]
[ro.secure]: [1]
[ro.serialno]: []
[ro.wifi.channels]: []
[ro.zygote]: [zygote64_32]
[selinux.reload_policy]: [1]
[service.bootanim.exit]: [1]
[status.battery.level]: [5]
[status.battery.level_raw]: [50]
[status.battery.level_scale]: [9]
[status.battery.state]: [Slow]
[sys.boot_completed]: [1]
[sys.sysctl.extra_free_kbytes]: [43200]
[sys.sysctl.tcp_def_init_rwnd]: [60]
[sys.usb.config]: [adb]
[sys.usb.state]: [adb]
[vold.has_adoptable]: [1]
[wlan.driver.status]: [unloaded]
[xmpp.auto-presence]: [true]

Подключить ADB к устройству через WiFi

Стандартная конфигурация ADB включает подключение USB к физическому устройству.
Если вы предпочитаете, вы можете переключиться в режим TCP / IP и подключить ADB через WiFi.

Не внедренное устройство

  1. Получить в той же сети:

    • Убедитесь, что ваше устройство и компьютер находятся в одной сети.
  2. Подключите устройство к главному компьютеру с помощью USB-кабеля.

  3. Подключить adb к устройству через сеть:

    Пока ваше устройство подключено к adb через USB, выполните следующую команду, чтобы прослушать TCP / IP-соединение на порту (по умолчанию 5555):

    • Введите adb tcpip <port> (переключитесь в режим TCP / IP).
    • Отсоедините кабель USB от целевого устройства.
    • Тип adb connect <ip address>:<port> (порт не является обязательным, по умолчанию 5555).

    Например:

    adb tcpip 5555
    adb connect 192.168.0.101:5555
    

    Если вы не знаете IP-адрес своего устройства, вы можете:

    • проверьте IP-адрес в настройках WiFi вашего устройства.
    • используйте ADB для обнаружения IP (через USB):
      1. Подключите устройство к компьютеру через USB
      2. В командной строке введите команду adb shell ifconfig и скопируйте IP-адрес своего устройства

    Чтобы вернуться к отладке через USB, выполните следующую команду:

    adb usb
    

    Вы также можете подключить ADB через WiFi, установив плагин в Android Studio. Для этого перейдите в « Настройки»> «Плагины» и «Храните репозитории», найдите « ADB WiFi» , установите его и снова запустите Android Studio. Вы увидите новый значок на панели инструментов, как показано на следующем рисунке. Подключите устройство к главному компьютеру через USB и щелкните по этому значку AndroidWiFiADB . Появится сообщение о том, подключено ли ваше устройство или нет. Как только он подключится, вы можете отключить USB-порт.

    Значок новой панели инструментов


Укорененное устройство

Примечание. Некоторые устройства, которые внедрены, могут использовать приложение ADB WiFi из Play Маркета, чтобы включить это простым способом. Кроме того, для некоторых устройств (особенно с CyanogenMod ROM) эта опция присутствует в настройках разработчика среди настроек. Включение этого параметра даст вам IP-адрес и номер порта, необходимые для подключения к adb , просто выполнив adb connect <ip address>:<port> .

Когда у вас есть внедренное устройство, но у вас нет доступа к USB-кабелю

Процесс подробно объясняется в следующем ответе: http://stackoverflow.com/questions/2604727/how-can-i-connect-to-android-with-adb-over-tcp/3623727#3623727 Наиболее важные команды показаны ниже.

Откройте терминал в устройстве и введите следующее:

su
setprop service.adb.tcp.port <a tcp port number>
stop adbd
start adbd

Например:

setprop service.adb.tcp.port 5555

И на вашем компьютере:

adb connect <ip address>:<a tcp port number>

Например:

adb connect 192.168.1.2:5555

Чтобы отключить его:

setprop service.adb.tcp.port -1
stop adbd
start adbd

Избегайте таймаута

По умолчанию adb истечет через 5000 мс. Это может случиться в некоторых случаях, таких как медленный WiFi или большой APK.

Простое изменение конфигурации Gradle может сделать трюк:

android {
    adbOptions {
        timeOutInMs 10 * 1000
    }
}

Потяните (нажмите) файлы с (на) устройства

Вы можете вытащить (загрузить) файлы с устройства, выполнив следующую команду:

adb pull <remote> <local>

Например:

adb pull /sdcard/ ~/

Вы также можете загружать (загружать) файлы с вашего компьютера на устройство:

adb push <local> <remote>

Например:

adb push ~/image.jpg /sdcard/

Пример извлечения базы данных с устройства

sudo adb -d shell "run-as com.example.name cat /data/da/com.example.name /databases/DATABASE_NAME  > /sdcard/file

Перезагрузите устройство

Вы можете перезагрузить устройство, выполнив следующую команду:

adb reboot

Выполните эту команду для перезагрузки в загрузчик:

adb reboot bootloader

Перезагрузка в режим восстановления:

adb reboot recovery

Имейте в виду, что устройство не выключится первым!

Включение / выключение Wi-Fi

Включи:

adb shell svc wifi enable

Выключи:

adb shell svc wifi disable

Просмотр доступных устройств

Команда:

 adb devices

Пример результата:

List of devices attached
emulator-5554  device
PhoneRT45Fr54  offline
123.454.67.45  no device

Первый столбец - порядковый номер устройства

Второй столбец - состояние соединения

Документация для Android

Подключение устройства по IP-адресу

Введите эти команды в Android-устройство Terminal

su
setprop service.adb.tcp.port 5555
stop adbd
start adbd

После этого вы можете использовать CMD и ADB для подключения, используя следующую команду

adb connect 192.168.0.101.5555

И вы можете отключить его и вернуть ADB для прослушивания на USB-устройстве

setprop service.adb.tcp.port -1
stop adbd
start adbd

С компьютера, если у вас уже есть USB-доступ (не требуется root)

Еще проще переключиться на использование Wi-Fi, если у вас уже есть USB. Из командной строки на компьютере, на котором подключено устройство через USB, выполните команды

adb tcpip 5555
adb connect 192.168.0.101:5555

Замените 192.168.0.101 на IP-адрес устройства

Start / stop adb

Начать АБР:

adb kill-server

Остановить АБР:

adb start-server

Просмотр логарифма

Вы можете запустить logcat как команду adb или непосредственно в приглашении оболочки вашего эмулятора или подключенного устройства. Чтобы просмотреть выход журнала с помощью adb , перейдите в каталог SDK platform-tools / и выполните:

$ adb logcat

Кроме того, вы можете создать соединение с устройством и затем выполнить:

$ adb shell
$ logcat

Одна полезная команда:

adb logcat -v threadtime

Это отображает дату, время вызова, приоритет, тег и PID и TID потока, выдающего сообщение в формате длинного сообщения.


фильтрация

Журналы Logcat получили так называемые уровни журналов:

V - Verbose, D - Debug, I - Info, W - Предупреждение, E - Ошибка, F - Фатальный, S - Беззвучный

Вы также можете фильтровать logcat по уровню журнала. Например, если вы хотите только выводить уровень отладки:

adb logcat *:D

Logcat можно отфильтровать по имени пакета, конечно, вы можете объединить его с фильтром уровня журнала:

adb logcat <package-name>:<log level>

Кроме того, можно фильтровать с помощью Grep журнала (больше на фильтрации вывода LogCat здесь ):

adb logcat | grep <some text>

В Windows фильтр можно использовать с помощью findstr, например:

adb logcat | findstr <some text>

Чтобы просмотреть альтернативный буфер журнала [main | events | radio], запустите logcat с параметром -b :

adb logcat -b radio

Сохранить вывод в файле:

adb logcat > logcat.txt

Сохраните вывод в файле, а также просмотрите его:

adb logcat | tee logcat.txt

Очистка журналов:

adb logcat -c

Прямая команда ADB для определенного устройства в настройке нескольких устройств

1. Настроить устройство по серийному номеру

Используйте параметр -s а затем имя устройства, чтобы выбрать, на каком устройстве должна запускаться команда adb . Параметры -s должны быть сначала в строке, перед командой.

adb -s <device> <command>

Пример:

adb devices

List of devices attached
emulator-5554       device
02157df2d1faeb33    device

adb -s emulator-5554 shell

Пример # 2:

adb devices -l

List of devices attached
06157df65c6b2633    device usb:1-3 product:zerofltexx model:SM_G920F device:zeroflte
LC62TB413962        device usb:1-5 product:a50mgp_dug_htc_emea model:HTC_Desire_820G_dual_sim device:htc_a50mgp_dug

adb -s usb:1-3 shell

2. Нацеливайте устройство, если подключен только один тип устройства

Вы можете настроить целевой эмулятор только на -e

adb -e <command>

Или вы можете настроить таргетинг только на подключенное USB-устройство на -d

adb -d <command>

Выполнение снимков экрана и видео (только для kitkat) с дисплея устройства

Снимок экрана: вариант 1 (чистый adb)

Команда adb shell позволяет нам выполнять команды с использованием встроенной оболочки устройства. Команда screencap shell захватывает содержимое, видимое в данный момент на устройстве, и сохраняет его в заданный файл изображения, например /sdcard/screen.png :

adb shell screencap /sdcard/screen.png

Затем вы можете использовать команду pull для загрузки файла с устройства в текущий каталог на вашем компьютере:

adb pull /sdcard/screen.png

Снимок экрана: Вариант 2 (быстрее)

Выполните следующий однострочный:

(Зефир и ранее):

adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen.png

(Нугат и позже):

adb shell screencap -p > screen.png

Флаг -p перенаправляет вывод команды screencap в stdout. Выражение Perl, которое транслируется, очищает некоторые проблемы конца строки в Marshmallow и ранее. Затем поток записывается в файл с именем screen.png в текущем каталоге. См. Эту статью и эту статью для получения дополнительной информации.

видео

это работает только в KitKat и только через ADB. Это не работает ниже Kitkat Чтобы начать запись экрана вашего устройства, выполните следующую команду:

adb shell screenrecord /sdcard/example.mp4 Эта команда начнет запись экрана вашего устройства с использованием настроек по умолчанию и сохранит полученное видео в файл /sdcard/example.mp4 на вашем устройстве.

Когда вы закончите запись, нажмите Ctrl + C (z в Linux) в окне командной строки, чтобы остановить запись на экране. Затем вы можете найти файл записи экрана в указанном вами местоположении. Обратите внимание, что запись на экране сохраняется во внутреннем хранилище вашего устройства, а не на вашем компьютере.

Настройки по умолчанию - использовать стандартное разрешение экрана вашего устройства, кодировать видео с битрейтом 4 Мбит / с и устанавливать максимальное время записи экрана на 180 секунд. Для получения дополнительной информации о параметрах командной строки, которые вы можете использовать, выполните следующую команду:

adb shell screenrecord –help , Это работает без укоренения устройства. Надеюсь это поможет.

Очистить данные приложения

Можно удалить пользовательские данные определенного приложения с помощью adb :

adb shell pm clear <package>

Это то же самое, что и для просмотра настроек на телефоне, выберите приложение и нажмите кнопку очистки данных.

  • pm вызывает диспетчер пакетов на устройстве
  • clear удаляет все данные, связанные с пакетом

Отправка трансляции

Можно отправлять трансляцию BroadcastReceiver с помощью adb .

В этом примере мы отправляем трансляцию с действием com.test.app.ACTION и string extra в bundle 'foo'='bar' :

adb shell am broadcast -a action com.test.app.ACTION --es foo "bar"

Вы можете поместить любой поддерживаемый тип в пакет, а не только строки:

--ez - boolean
--ei - целое число
--el - long
-ef - float
--eu - uri
--eia - массив int (разделенный символом ',')
--ela - длинный массив (разделенный символом ',')
--efa - массив с плавающей точкой (разделенный символом ',')
--esa - строковый массив (разделенный символом ',')

Для отправки намерения использовать определенный параметр package / class -n или -p .
Отправка в пакет:

-p com.test.app

Отправка на конкретный компонент ( SomeReceiver класса в com.test.app package ):

-n com.test.app/.SomeReceiver

Полезные примеры:

Установка и запуск приложения

Чтобы установить файл APK , используйте следующую команду:

adb install path/to/apk/file.apk

или если приложение существует, и мы хотим переустановить

adb install -r path/to/apk/file.apk 

Чтобы удалить приложение , мы должны указать его пакет

adb uninstall application.package.name

Используйте следующую команду для запуска приложения с предоставленным именем пакета (или определенной деятельностью в приложении):

adb shell am start -n adb shell am start <package>/<activity>

Например, чтобы запустить Waze:

adb shell am start -n adb shell am start com.waze/com.waze.FreeMapAppActivity

Резервное копирование

Вы можете использовать команду adb backup для резервного копирования вашего устройства.

adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] 
           [-system|nosystem] [<packages...>]

-f <filename> указать имя файла по умолчанию: создает backup.ab в текущем каталоге

-apk|noapk включить / отключить резервное копирование по умолчанию .apks : -noapk

-obb|noobb включить / отключить резервное копирование дополнительных файлов по умолчанию: -noobb

-shared|noshared к содержимому общего хранилища / содержимого SD-хранилища noshared по умолчанию: -noshared

-all резервную копию всех установленных Apllications

-system|nosystem : система включает системные приложения по умолчанию: -система

<packages> список пакетов для резервного копирования (например , com.example.android.myapp) (не требуется , если -all указано)


Для полной резервной копии устройства, включая все, используйте

adb backup -apk -obb -shared -all -system -f fullbackup.ab

Примечание. Выполнение полной резервной копии может занять много времени.


Чтобы восстановить резервную копию, используйте

adb restore backup.ab

Установка ADB в системе Linux

Как установить Android Debugging Bridge (ADB) в систему Linux с терминалом, используя репозитории вашего дистрибутива.

Установите в систему Ubuntu / Debian через apt:

sudo apt-get update
sudo apt-get install adb

Установите в систему Fedora / CentOS через yum:

sudo yum check-update
sudo yum install android-tools

Установите в систему Gentoo с портом:

sudo emerge --ask dev-util/android-tools

Установите в систему openSUSE с помощью zypper:

sudo zypper refresh
sudo zypper install android-tools 

Установите в систему Arch с помощью pacman:

sudo pacman -Syyu
sudo pacman -S android-tools

Список всех разрешений, требующих предоставления времени выполнения от пользователей на Android 6.0

adb shell pm list permissions -g -d 

Просмотр внутренних данных приложения (данные / данные / ) на устройстве

Во-первых, убедитесь, что ваше приложение может быть скопировано в AndroidManifest.xml , т android:allowBackup не является false .

Команда резервного копирования:

adb -s <device_id> backup -noapk <sample.package.id>

Создайте tar с командой dd:

dd if=backup.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" > backup.tar

Извлеките смолу:

tar -xvf backup.tar

Затем вы можете просмотреть извлеченный контент.

Просмотреть стек активности

adb -s <serialNumber> shell dumpsys activity activities

Очень полезно при использовании вместе с командой watch unix:

watch -n 5 "adb -s <serialNumber> shell dumpsys activity activities | sed -En -e '/Stack #/p' -e '/Running activities/,/Run #0/p'"

Просмотр и извлечение файлов кеша приложения

Вы можете использовать эту команду для перечисления файлов для собственного отлаживаемого apk:

adb shell run-as <sample.package.id> ls /data/data/sample.package.id/cache

И этот скрипт для вытаскивания из кеша, сначала скопируйте содержимое на SDCard, потяните, а затем удалите его в конце:

#!/bin/sh
adb shell "run-as <sample.package.id> cat '/data/data/<sample.package.id>/$1' > '/sdcard/$1'"
adb pull "/sdcard/$1"
adb shell "rm '/sdcard/$1'"

Затем вы можете вытащить файл из кеша следующим образом:

./pull.sh cache/someCachedData.txt

Получить файл базы данных через ADB

sudo adb -d shell "run-as com.example.name cat /data/da/com.example.name /databases/STUDENT_DATABASE  > /sdcard/file


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow