Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does ADB commands break a bash script loop?

Tags:

bash

adb

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
like image 568
L. D. James Avatar asked Jun 19 '17 15:06

L. D. James


People also ask

How do you stop an infinite loop in a script?

To stop this infinite loop, press Ctrl + C and then press y and then Enter.

How do I stop a shell script from looping?

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!"

How do I escape adb shell?

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.


2 Answers

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)
like image 126
Chris Dodd Avatar answered Sep 21 '22 07:09

Chris Dodd


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.

like image 34
Alex P. Avatar answered Sep 21 '22 07:09

Alex P.