Why won't function return until background process ends?

Consider this script:

#!/bin/bash
function start {
  leafpad &
  echo $!
}
PID=$(start)
echo "PID is $PID"

The script does not continue past its closing brace until the leafpad process ends, even though it is a background process.

Why is this? Is it possible to launch a background process from a function?

Asked By: user234565

||

The function returns, but the command substitution blocks, because you created a background job, but you still have your stdout fd opened. Just close it by adding >/dev/null before the &.

#!/bin/bash
function start {
  leafpad >/dev/null &
  echo $!
}
PID=$(start)
echo "PID is $PID"

If you want your process to have also stdin, stdout, stderr closed, use this :

leafpad >/dev/null 0>&1 2>&1 &

This will close stdin (0), stdout (1), and stderr (2), then background (&).
Also, when using these stream redirections don’t forget they are “duped”, that means duplicated in the order of execution.

1>/dev/null 2>&1

and

2>&1 1>/dev/null

are not the same ! In the former, you are duplicating a stream to /dev/null (which is what you want), in the latter, you are duplicating /dev/stdout to stderr, and then, closing stdout. So any message sent to stderr will appear in your console.

Answered By: Adrien M.