2

There's a wealth of stack exchange answers regarding nohup, here's a couple for reference:
When do you need 'nohup' if you're already forking using '&'?
Why use "nohup &" rather than "exec &"

The canonical answer seems to be that using nohup prevents the process from ending when the terminal is closed, so commands like this:
nohup mycommand >& mycommand_output.txt &
will still be running the next time I log in, and it saves the output so I can check it later.

But if I save a few keystrokes:
mycommand >& mycommand_output.txt &
is also still running when I next log in.

It's different from nohup since I can stop it with a kill -HUP. When I log back in, ps -x says the processes's TTY is now ?, so the process isn't still connected to a terminal.

Why doesn't the process stop when I exit the shell?
Can I safely assume my processes won't end if I don't use nohup?

In case it matters, my current environment involves SSHing into a Debian machine from an Ubuntu machine.

2

Can I safely assume my processes won't end if I don't use nohup

No. If the terminal hangs up and it had an interactive shell as a session leader, the shell will get a SIGHUP and resend it to its jobs that haven't been disowned.

If the shell exits voluntarily, it'll send SIGHUP to its jobs if the huponexit option is on.

If the shell exits voluntarily and there are owned jobs that are stopped, bash will kill them with SIGTERM (not sure if this is standard behavior).

If the shell exits voluntarily and there are disowned jobs that are stopped, the terminal driver will kill them with SIGHUP (this is definitely standard-mandated).

So you can still get killed with SIGHUP in various scenarios.

That said, from looking at a nohup source code at http://src.gnu-darwin.org/src/usr.bin/nohup/nohup.c.html, it appears to more or less doable in pure shell:

nohup_sh()
(
    set -e
    if [ -t 1]; then
        exec >> nohup.out || exec >> "$HOME/nohup.out"
    fi
    if [ -t 0 ]; then
        exec 0</dev/null
    fi
    if [ -t 2 ]; then
        exec 2>&1
    fi
    trap '' HUP #ignore SIGHUP (inheritable)
    set -m || : #to prevent SIGINT and SIGQUIT from being ignored
    #(probably not needed, but the nohup binary won't ignore them, unlike
    # & without set -m)

    command "$@" &
)

You might not need the extra stuff outside of trap '' HUP, although the job will get SIGPIPE if it tries to write to a disconnected terminal (which is what the redirections prevent).

  • "the huponexit option" - this is what I was missing. I hadn't realized such an option existed, let alone that it might be set to off. This other answer had some more information about huponexit. – Elliot Way Jul 19 '17 at 16:24
3

Why doesn't the process stop when I exit the shell?

Probably because you told the shell to disown it. Or you might not be using an interactive job control shell as your session leader process.

The combined session+process groups model that the world settled upon in the 1980s works like this: There is a session leader process. That is what gets the hangup signal from the terminal line discipline when the terminal is hung up. It is expected to amplify that signal, itself sending the signal to all of the "jobs" that it has spawned. Interactive job control shells will do this; most other programs do not expect to have the responsibilities of session leaders, and will not.

Using nohup makes the processes in those "jobs" ignore the hangup signal when the session leader sends it to them. Using disown makes the session leader shell forget about a job, so that it never sends a hangup signal to it in the first place.

Can I safely assume my processes won't end if I don't use nohup?

No. If they have not been disowned, then they will be sent a hangup signal by a session leader interactive job control shell process.

Furthermore: The systemd people have tried to implement a user-space mechanism equivalent to kernel sessions, but they have made a bit of a pig's ear of it, which introduces further complications on (some) systemd operating systems. At systemd session hangup instead of sending SIGHUP to just the session leader as the kernel's line discipline does, they erroneously send SIGTERM to all processes, erroneously signifying shutdown rather than hangup.

SIGTERM to all processes is of course what happens, in the standard session+process groups model, at system shutdown; and that kills all processes, including disowned ones and ones that ignore the hangup signal. It will kill your processes that have been neither disowned nor nohuped, as well of course.

Further reading

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.