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.
It's a little hard to diagnose, as you don't give source for myproc
, but I suspect that your problem has something to do with "controlling TTY". I wrote a small shell script that just calls sleep 100
. I ran it under nohup
:
$ nohup ./sleeper > sleeper.out &
[1] 25305
-bash-3.2$ jobs
[1]+ Running nohup ./sleeper > sleeper.out &
-bash-3.2$ ps -l -p 25305
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 429624 25305 18252 0 77 0 - 15961 wait pts/0 00:00:00 sleeper
If you look at the ps
output, you see a column named "TTY". At least some versions of nohup
(the one I used above is from GNU coreutils, version 5.97, so relatively old). When I exited the bash shell from which I started sleeper
, the TTY column changed to '?', meaning that sleeper
didn't have one.
If myproc
doesn't deliberately detach itself from it's controlling TTY, it's still possible to get things like a SIGPIPE signal if it tries to write to stdout. It seems to me other things are possible, but I can't recall or google anything up.
If you can find or compile "daemonize", you might want to try it. If myproc
is compiled, you could modify the source to call the daemon(3)
library function.
Best Answer
No.
disown
does not remove a job from the current session [1], does not detach it from the terminal, and does not affect which signals the kernel will send it when the session leader exits or when the controlling terminal is torn down.disown
only works on bash's own job table, only changes bash's idea of which jobs it's in control of, and only affects bash's own behavior, namely which jobs it will resend aSIGHUP
received by the bash process. ThatSIGHUP
resending is an extra feature ofbash
[2], not required by the standard and not related to the job control provided by the OS.You can see it with a simple example, where I'm using
script(1)
to create a pty and an interactive shell session running in it:Here the kernel sends a
SIGHUP
signal to the background process group (= job) because one of its processes is stopped, and disowning it will not prevent that from happening.All processes from the
sh -c '...'
are part of the same job, including the "background"sleep &
; shell scripts don't do job control by default.If no members of the background process group are stopped, no
SIGHUP
is sent:Finally, bash will send a
SIGHUP
to all the jobs from its table (only those started by itself and not disowned), no matter if bash is the session leader or not, or if the jobs are running, stopped, etc:[1] which would be impossible to do anyway;
setsid()
is only able to make into a new session a process which is not a process group leader, there is no way to move a whole job into a new or existing session.[2] which is documented in the bash's manpage:
There's is also
shopt -s huponexit
which cause a login bash shell to send aHUP
to its jobs upon exiting (whether because of a signal or not), which again overlaps in confusing ways with the standard job control features of the OS.