Why does ADB commands break a bash script loop?

2019-01-15 19:44发布

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

标签: bash adb
2条回答
冷血范
2楼-- · 2019-01-15 20:03

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.

查看更多
该账号已被封号
3楼-- · 2019-01-15 20:19

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)
查看更多
登录 后发表回答