trap '[[ -v SERVER_PID ]] && pkill -P $SERVER_PID' EXIT
coproc SERVER { server; }
url=$(<&${SERVER[0]} perl -nle 'm/(http\S+)/; print $1; exit 0;')
run-thing --using-server="$url"
Here, -v
checks if the variable was set, in case the script fails before launching the server. Since the coprocess is not launched directly but in a subshell, you want to use pkill -P
that kills a process by its parent PID. Finally, <&${SERVER[0]}
reads from its stdout. Runnable code that approximates the above:
$ cat test.sh
trap 'pkill -P $COPROC_PID' EXIT
coproc { python3 -uc 'import time; print("Listening on http://localhost:123"); time.sleep(99)'; }
url=$(<&${COPROC[0]} perl -nle 'm/(http\S+)/; print $1; exit 0;')
echo "using server at $url, server $(pgrep python >/dev/null && echo is running)"
$ bash test.sh; ps aux | pgrep python || echo server successfully killed
using server at http://localhost:123, server is running
Terminated
server successfully killed
trap "kill 0" EXIT
{ url=$(perl -nle 'm/(http\S+)/; print $1; exit 0;'); } < <(server)
run-thing --using-server="$url"
This was found thanks to the helpful advice from libera's #bash. Runnable code that approximates the above:
$ cat test.sh
trap "kill 0" EXIT
{ url=$(perl -nle 'm/(http\S+)/; print $1; exit 0;'); } \
< <(python3 -uc 'import time; print("Listening on http://localhost:123"); time.sleep(99)')
echo "using server at $url, server $(pgrep python >/dev/null && echo is running)"
$ bash test.sh; ps aux | pgrep python || echo server successfully killed
using server at http://localhost:123, server is running
server successfully killed
I'm not entirely sure why I need {}
, which is a command grouping. It's like ()
but it doesn't spawn a subshell. kill 0
will kill all processes in the current process group. This may kill the process that started current script. You can also kill the server directly. Just like coproc
does, <()
spawns a subshell, so you want to find the process by parent:
{ url=$(perl -nle 'm/(http\S+)/; print $1; exit 0;');
run-thing --using-server="$url";
} < <(server)
pkill -P $!