I'm noticing a problem when running multiple adb commands from a shell script loop most of the commands does not execute.
This is an example script.
Script name: adbscript.sh
:
#!/bin/bash
devicecount=0
while read device; do
((devicecount++))
serialno="NA"
appinstallcount="NA"
echo "Processing Device #$devicecount: $device"
# serialno=$(adb -s $device shell getprop ro.serialno)
# appinstallcount=$(adb -s $device shell pm list packages | wc -l)
echo -e "Device: $device | Serialno: $serialno | Apps installed: $appinstallcount\n"
done < <(adb devices | egrep "\bdevice\b" | awk '{print $1}')
echo "Finished."
Output with adb commands commented out
I have 5 devices connected. When running from the bash file without theadb commands this is the output. It iterates through each of the 5 loops.
Processing Device #1: 192.168.15.93:5123 Device: 192.168.15.93:5123 | Serialno: NA | Apps installed: NA Processing Device #2: 192.168.15.95:5123 Device: 192.168.15.95:5123 | Serialno: NA | Apps installed: NA Processing Device #3: emulator-5554 Device: emulator-5554 | Serialno: NA | Apps installed: NA Processing Device #4: 31005c77c8cfb200 Device: 31005c77c8cfb200 | Serialno: NA | Apps installed: NA Processing Device #5: 98883837594d4f5453 Device: 98883837594d4f5453 | Serialno: NA | Apps installed: NA Finished.
Output with loop containing ADB
commands
When the adb shell
command is uncommented it only properly iterates lines of the first loop. This is the output with the adb
command uncommented:
Processing Device #1: 192.168.15.93:5123 Device: 192.168.15.93:5123 | Serialno: 98883837594d4f5453 | Apps installed: 442 Finished.
Can someone explain this behavior and what would have to be done to have all the lines and all the loops processed?
By the way, this is the output supplied to the script (one liner command and output):
$ adb devices | egrep "\bdevice\b" | awk '{print $1}'
192.168.15.93:5123
192.168.15.95:5123
emulator-5554
31005c77c8cfb200
98883837594d4f5453
To stop this infinite loop, press Ctrl + C and then press y and then Enter.
Breaking from a while LoopUse the break statement to exit a while loop when a particular condition realizes. The following script uses a break inside a while loop: #!/bin/bash i=0 while [[ $i -lt 11 ]] do if [[ "$i" == '2' ]] then echo "Number $i!" break fi echo $i ((i++)) done echo "Done!"
To exit adb and return to the system shell use the $q or $Q command. To stop the debugger press <Ctrl>D. NOTE: adb cannot be stopped by pressing the Quit or Interrupt key.
adb shell
connects stdin to the command running on the device, which will generally consume stdin until a EOF is reached. So these commands consume all of the rest of your device names, causing the loop to exit.
Run adb
with a stdin redirection, so they get an immediate EOF without messing with what you're trying to loop over:
serialno=$(adb </dev/null -s $device shell getprop ro.serialno)
appinstallcount=$(adb </dev/null -s $device shell pm list packages | wc -l)
While @ChrisDodd's root cause analysis is correct and his solution works fine in general, for adb
automation purposes it is preferable to use adb exec-out
instead of suggested adb </dev/null shell
for simple adb shell commands.
Also why use grep
when you are already using awk
?
for device in $(adb devices | awk '$2=="device"{print$1}')
do
serialno=$(adb -s $device exec-out getprop ro.serialno)
appinstallcount=$(adb -s $device exec-out pm list packages | wc -l)
...
done
For adb exec-out
to work you need both your host PC and devices have somewhat recent adb
(or adbd
in case of devices) version - platform-tools
v24+ and Android 5.1+ should do.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With