Is there a way of running adb commands on all connected devices? To uninstall an app from all connected devices with "adb uninstall com.example.android".
The commands I am interested in is mainly install and uninstall.
I was thinking about writing a bash script for this, but I feel like someone should have done it already :)
Create a bash (adb+)
adb devices | while read line
do
if [ ! "$line" = "" ] && [ `echo $line | awk '{print $2}'` = "device" ]
then
device=`echo $line | awk '{print $1}'`
echo "$device $@ ..."
adb -s $device $@
fi
done
use it with
adb+ //+ command
Building on @Oli's answer, this will also let the command(s) run in parallel, using xargs
. Just add this to your .bashrc
file:
function adball()
{
adb devices | egrep '\t(device|emulator)' | cut -f 1 | xargs -t -J% -n1 -P5 \
adb -s % "$@"
}
and apply it by opening a new shell terminal, . ~/.bashrc
, or source ~/.bashrc
.
- If you only want to run on devices (or only on emulators), you can change the
(device|emulator)
grep by removing the one you don't want. This command as written above will run on all attached devices and emulators.
- the
-J%
argument specifies that you want xargs to replace the first occurrence of %
in the utility with the value from the left side of the pipe (stdin).
NOTE: this is for BSD (Darwin / Mac OS X) xargs
. For GNU/Linux xargs
, the option is -I%
.
-t
will cause xargs to print the command it is about to run immediately before running it.
-n1
means xargs should only use at most 1
argument in each invocation of the command (as opposed to some utilities which can take multiple arguments, like rm
for example).
-P5
allows up to 5
parallel processes to run simultaneously. If you want instead to run the commands sequentially, simply remove the entire -P5
argument. This also allows you to have two variations of the command (adball
and adbseq
, for example) -- one that runs in parallel, the other sequentially.
To prove that it is parallel, you can run a shell command that includes a sleep in it, for example:
$ adball shell "getprop ro.serialno ; date ; sleep 1 ; date ; getprop ro.serialno"
You can use this to run any adb
command you want (yes, even adball logcat
will work! but it might look a little strange because both logs will be streaming to your console in parallel, so you won't be able to distinguish which device a given log line is coming from).
The benefit of this approach over @dtmilano's &
approach is that xargs
will continue to block the shell as long as at least one of the parallel processes is still running: that means you can break out of both commands by simply using ^C
, just like you're used to doing. With dtmilano's approach, if you were to run adb+ logcat
, then both logcat processes would be backgrounded, and so you would have to manually kill the logcat process yourself using ps
and kill
or pkill
. Using xargs makes it look and feel just like a regular blocking command line, and if you only have one device, then it will work exactly like adb
.
This is an improved version of the script from 強大な. The original version was not matching some devices.
DEVICES=`adb devices | grep -v devices | grep device | cut -f 1`
for device in $DEVICES; do
echo "$device $@ ..."
adb -s $device $@
done
To add in the ~/.bashrc or ~/.zshrc:
alias adb-all="adb devices | awk 'NR>1{print \$1}' | parallel -rkj0 --tagstring 'on {}: ' adb -s {}"
Examples:
$ adb-all shell date
$ adb-all shell getprop net.hostname
$ adb-all sideload /path/to/rom.zip
$ adb-all install /path/filename.apk
$ adb-all push /usr/local/bin/frida-server-arm64 /data/local/tmp/frida-server
Explanation: awk
extracts the device id/host (first column: print $1
) of every lines except the first one (NR>1
) to remove the "List of devices attached" header line), then gnu parallel runs adb -s <HOSTNAME> <whatever-is-passed-to-the-alias>
on whatever non-empty line (-r
) in the order specified (-k
, to avoid random order / fastest response order) and prepend each line with on <DEVICE>:\t
for clarity, all in parallel (-j0
, possible to set another number to define how many adb should be ran in parallel instead of unlimited).
:)
adb wrapper supports selecting multiple targets for adb commands and parallel execution.
From its README:
# Installation
./install.sh ~/apps/android-sdk-linux
# Execute adb commands on all connected devices.
adb set-target all
# Execute adb commands on given devices.
adb set-target emulator-5554 C59KGT14263422
# Use GNU parallel for parallel install.
adb set-parallel true
(Disclaimer: I have written half of it)