13

Consider a shell script executed by Sh, not Bash (and I can't change it, and can't use a shebang, it's ignored). The & operator works, but disown $! does not and makes Sh complains “disown: not found”.

How do I detach a background process from specifically Sh? I mean, doing from Sh the same as disown do from Bash.

4
  • 4
    In scripts, disown has no effect anyway (is not needed) Jul 31, 2014 at 20:20
  • 1
    How no effect? You mean the shell session which launched the background process will close and let the background process continue? You mean I don't need disown or similar at all?
    – Hibou57
    Jul 31, 2014 at 20:24
  • 5
    Yes, try sh -c 'sleep 100 &' and see that sleep is still running after sh has returned (sh -c is to run inline scripts). Jul 31, 2014 at 20:25
  • 1
    I checked it, indeed, it's as you say. So that's strange I had issues with this in the past, and that's due to these issues I wanted to use disown now. I will leave this question open for now and will either complete it or close it, depending on further future cases.
    – Hibou57
    Jul 31, 2014 at 21:04

1 Answer 1

6

First let's see what Bash's disown command does. From Bash manual:

The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP. To prevent the shell from sending the SIGHUP signal to a particular job, it should be removed from the jobs table with the disown builtin (see Job Control Builtins) or marked to not receive SIGHUP using disown -h.

If the huponexit shell option has been set with shopt (see The Shopt Builtin), Bash sends a SIGHUP to all jobs when an interactive login shell exits.

What this means is that it's the shell itself, if it receives SIGHUP, forwards it to the background jobs. If the shell exits (and huponexit had't been enabled), the background processes—which don't have a controlling terminal—don't get SIGHUP on terminal closing.

So if your concern is to prevent SIGHUP to a process launched from a shell wrapper, like e.g.

#!/bin/sh
my-command arg &

then there's no need in disown-like functionality, since my-command will not receive SIGHUP unless the shell gets it before exiting.

But, there still is a problem if you want to run a child from a script that will continue execution for some time after launching the child, like e.g. here:

#!/bin/sh
sleep 55555 &
sleep 3333 # some long operation we don't care about

The script above will terminate the sleep 55555 command if the script's controlling terminal closes. Since Bourne shell doesn't have the disown builtin that Bash, Ksh and some other shells have, we need another tool. That tool is nohup(1). The above script, in which we aren't interested in the stdout and stderr of the child process, can be modified to the following to avoid sleep getting SIGHUP:

#!/bin/sh
nohup sleep 55555 >/dev/null 2>&1 &
sleep 3333 # some long operation we don't care about

The redirection to /dev/null is to avoid getting the nohup.out file in current directory. Without the redirection, this file will contain the output of the nohupped process.

1
  • so we can delete the file with rm nohup.out if we still want standard out and error from our commands Jun 28, 2022 at 20:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .