21

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?

22

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.

  • Confirmed on my system – user120161 Jul 27 '15 at 0:21
  • 10
    You're not closing the streams, you're redirecting them. – dcat Jul 27 '15 at 1:21
  • 4
    to close; n>&- where n is the file descriptor. – dcat Jul 27 '15 at 1:46
  • 1
    @dcat: Yes, but redirection to / from /dev/null won't lead to i/o errors when a process tries to write its stdout, but finds that 1 is an invalid FD. So the terminology in the post is wrong, not the actual bash programming. (Actually, duplicating FD 1 to 0 means that stdin will be a file-descriptor opened with O_RDONLY, which will probably give an error (rather than the desired no-bytes-available) when the process tries to read.) e.g. wc >/dev/null 0>&1 -> wc: standard input: Bad file descriptor – Peter Cordes Jul 27 '15 at 2:09
  • 1
    @PeterCordes - Closing the old descriptor and redirecting the new one need not be mutually exclusive. exec <&- >&- <>/dev/null >&0 handles stdin/out pretty exhaustively. It makes a difference in zsh at least which will sort of concatenate all opens on the same descriptor automatically when multios is set. – mikeserv Jul 27 '15 at 2:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.