24

disown

  • causes a shell not to send SIGHUP to its disowned job when the shell terminates, and

  • removes the disowned job from the shell's job control.

Is the first the result of the second? In other words, if a process started from a shell is removed from the shell's job control by any way, will the shell not send SIGHUP to the process when the shell terminates?

disown -h still keeps a process under a shell's job control. Does it mean that disown -h makes a process still receives SIGHUP sent from the shell, but sets up the action of SIGHUP by the process to be "ignore"? That sounds similar to nohup.

$ sleep 123 & disown -h
[1] 26103
$ jobs
[1]+  Running                 sleep 123 &
$ fg 1
sleep 123
$ ^Z
[1]+  Stopped                 sleep 125
$ bg 1
[1]+ sleep 123 &
$ exit

$ ps aux | grep sleep
t        26103  0.0  0.0  14584   824 ?        S    15:19   0:00 sleep 123

Do disown -h and nohup work effectively the same, if we disregard their difference in using a terminal?

Thanks.

Tim
  • 98,580
  • 191
  • 570
  • 977
  • Another difference not discussed here is that if you aren't using `nohup`, you need to redirect stdin/stdout/stderr away from the TTY (should your original shell be connected to one) yourself. (OTOH, I actually consider that better practice than relying on an egregious hardcoded default like `./nohup.out`). – Charles Duffy Nov 26 '18 at 22:17

2 Answers2

26

nohup and disown -h are not exactly the same thing.

With disown, a process is removed from the list of jobs in the current interactive shell. Running jobs after starting a background process and running disown will not show that process as a job in the shell. A disowned job will not receive a HUP from the shell when it exits (but see note at end).

With disown -h, the job is not removed from the list of jobs, but the shell would not send a HUP signal to it if it exited (but see note at end).

The nohup utility ignores the HUP signal and starts the given utility. The utility inherits the signal mask from nohup and will therefore also ignore the HUP signal. When the shell terminates, the process remains as a child process of nohup (and nohup is re-parented to init).

The difference is that the process started with nohup ignores HUP regardless of who sends the signal. The disowned processes are just not sent a HUP signal by the shell, but may still be sent the signal from e.g. kill -s HUP <pid> and will not ignore this.

Note that HUP is only sent to the jobs of a shell if

  • the shell is a login shell and the huponexit shell option is set, or
  • the shell itself recieves a HUP signal.

Relevant bits from the bash manual (my emphasis):

SIGNALS

[...]

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 signal to a particular job, it should be removed from the jobs table with the disown builtin (see SHELL BUILTIN COMMANDS below) or marked to not receive SIGHUP using disown -h.

If the huponexit shell option has been set with shopt, bash sends a SIGHUP to all jobs when an interactive login shell exits.

disown [-ar] [-h] [jobspec ... | pid ... ]

Without options, remove each jobspec from the table of active jobs. [...] If the -h option is given, each jobspec is not removed from the table, but is marked so that SIGHUP is not sent to the job if the shell receives a SIGHUP. [...]

Related:

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
  • I get `bash: disown: nohup: no such job` and same for `sleep` and `5` from `disown nohup sleep 5 &`. What did you mean by that second command from the last sentence? – Ruslan Nov 26 '18 at 20:54
  • @Ruslan Yes I'm missing a `&` in there (and the order of `nohup` and `disown` was also wrong). Thanks. Will update now. – Kusalananda Nov 26 '18 at 20:55
  • For example, https://unix.stackexchange.com/questions/484315/why-does-disown-h-make-chromium-browser-survive-closing-its-terminal-emulator – Tim Nov 26 '18 at 22:30
  • @Tim Sorry for the excessive editing of the answer. It took a while to get my head around it. I'm done now. – Kusalananda Nov 26 '18 at 23:04
  • Thanks. `disown` makes a shell not sent SIGHUP to a child by removing the child from the shell's job list. How does `disown -h` achieve the same? – Tim Nov 26 '18 at 23:14
  • @Tim Not exactly. Both `disown` and `disown -h` makes `bash` mark the process as one to not send the `HUP` signal to. `disown` additionally removes it from the job table. In my opinion, this builtin is confusing and does too many similar but not quite the same things. – Kusalananda Nov 26 '18 at 23:17
  • Minor thing that probably is worth also mentioning is that `disown` is shell built-in in `ksh` and `bash` ( don't know about others ) but there's GNU `nohup` standalone in `/usr/bin/nohup` on Ubuntu-based distros and then there's [csh built-in](https://docs.oracle.com/cd/E19455-01/806-0624/6j9vek5c1/index.html) (See NOTES section). – Sergiy Kolodyazhnyy Nov 27 '18 at 09:50
  • @pizdelect I'm flagging your comments as rude, which they are, which also deletes them. If you want to give me constructive criticism, please drop the name-calling. In your first comment from yesterday, you mentioned that "`nohup` executes through the utility". I did not understand what you mean by that. Also, if you want, you may suggest edits to my answer to make it better, or provide your own answer where you provide a better text. – Kusalananda Aug 28 '20 at 08:15
5

They are Different:

  • disown removes the job from the active jobs table. Then continues on with current job. With -h the proccess is NOT sent SIGHUP. It is instead left to die with the shell that contains it, when it recieves a SIGHUP.

  • nohup ignores the HUP. Then anything that would have been passed to the terminal by the proccess closing instead goes to a file nohup.out.

    nohup is defined by POSIX while disown is not.

Michael Prokopec
  • 2,202
  • 7
  • 21
  • 1
    What do you mean, "die with the shell that contains it"? Killing a parent process does not in and of itself kill a child. Programs whose terminals are closed *typically* die on account of failures related to attempts to interact with a file handle attached to the terminal's PTY, but if stdin/stdout/stderr are redirected elsewhere, that won't happen. – Charles Duffy Nov 12 '19 at 14:15