I'm trying to get the PID of a background job with command substitution. The background job is started with setsid. The problem is that the parent process is struck at the command substitution.
Here is an example script:
#!/bin/bash
if [ "$1" = "start" ]; then
while true; do date > "bg.date"; sleep 1; done &
echo $!
exit 0
fi
pid="$(setsid "$0" start)"
echo "pid=$pid"
./script startworks as expected (ie. exits immediately to bash prompt while background job is running).setsid ./script startalso works as expected.- But
./scriptdoes not work as expected: it does not print the PID (unless the background job is killed manually).
Command substitution is implemented via pipes. The read end waits for all writers to close, but you're keeping the write end open indefinitely as the stdout of your infinite loop.
You can redirect the loop to avoid this:
If the re-entrant
setsidwas part of an attempt to make the script not hang, you'll be pleased to know that this is unnecessary and you can rewrite it more robustly with a simple function.