Add a parallel_run.py tool

Sometimes when investigating a flake it is useful to add logging and
repeatedly run a command until the issue appears with the logging.
This can be tedious if the flake is rare. To make it easier I added a
simple parallel_run.py tool that can run a command in parallel
repeatedly until it fails and save the stdout from the failed run.

Usage:

% # Write a script that exits with 0 on failure and writes all output
% # to stdout.
% cat tst.sh
\#!/bin/bash
! (head -c32 /dev/urandom | hd | grep -E '\|.*a')

% # Run the script in parallel
% ./art/tools/parallel_run.py -j80 --out out.txt ./tst.sh
Temporary files in /tmp/tmp5013_ey7
1 runs
<snip>
31 runs

% # Examine output
% cat out.txt
00000000  6d e3 ac bf 1a 21 93 17  61 00 2a e0 8b f5 41 3b  |m....!..a.*...A;|

Test: ./art/tools/parallel_run.py -j70 --out out.txt ./tst.sh
Bug: 72608560
Change-Id: I83877ae1ccde5e843da20c5bd5a4f24e2e07fb19
1 file changed