Neha Agarwal Neha Agarwal - 1 year ago 96
Bash Question

Command stops the bash script befor it finishes

I have this script:

#!/usr/bin/bash
uninstall ()
{
echo "$device : uninstalling the app..."
adb -s $device uninstall "fr.inria.es.electrosmart.debug"
}
install_app ()
{
echo "$device : installing the app..."
adb -s $device install -r /run/netsop/u/sop-nas2a/vol/home_diana/nagarwal/StudioProjects/es-android/app/build/outputs/apk/app-debug.apk
}
install_tests ()
{
echo "$device : installing the tests..."
adb -s $device install -r /run/netsop/u/sop-nas2a/vol/home_diana/nagarwal/StudioProjects/es-android/app/build/outputs/apk/app-debug-androidTest.apk
}
run_tests ()
{
echo "$device : running the tests..."
adb -s $device shell "am instrument -w -r -e debug false -e class fr.inria.es.electrosmart.activities.TestAgreement fr.inria.es.electrosmart.debug.test/android.support.test.runner.AndroidJUnitRunner" || true
}

adb devices | while read line
do
if [ ! "$line" = "" ] && [ `echo $line | awk '{print $2}'` = "device" ]
then
device=`echo $line | awk '{print $1}'`
echo "$device [email protected] ..."
uninstall
install_app
install_tests
run_tests
fi
done


It's supposed to run the tests on all the connected devices. I have two devices connected to my computer. But the test only runs on the first device and the script stops before running on the second device.

I think that the command
adb -s $device shell "am instrument -w -r -e debug false -e class fr.inria.es.electrosmart.activities.TestAgreement fr.inria.es.electrosmart.debug.test/android.support.test.runner.AndroidJUnitRunner" || true
is responsible for crashing the script.

Any idea why is that happening? And how can I work around this.

Thanks in advance.

Answer Source

If abd is reading from stdin, it is consuming the data intended to be read by your while loop. To avoid this, try closing stdin for the body of the loop so nothing can eat the data:

adb devices | while read device label _; do
    if test "$label" = device; then
        echo "$device [email protected] ..."
        uninstall
        install_app
        install_tests
        run_tests
    fi <&-
done

Another common idiom is to read from a different file descriptor, or to redirect input from /dev/null or /dev/tty rather than closing the input. And, if you are on a system that doesn't have /dev/tty but want to have the inner loop read from the original script's stdin, you can do:

exec 3<&0
adb devices | while read device label _; do
   ...
   fi <&3
done

Of course, this requires that your script use a currently unused file descriptor for the dup, and hence is a bit fragile.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download