Right, so you want to run a command and then log out. Maybe it’s a massive database dump, a long-running scientific simulation, or a script that’s deploying your entire application. You’re not about to sit there staring at a terminal for the next six hours. You have things to do. A life to live. Or at least, other terminals to open.

You might think you can just start the process and close your laptop. Don’t. The moment your shell session ends—whether you log out, your SSH connection drops, or you simply close the terminal window—it sends a hangup signal (SIGHUP) to every single process it started. This is essentially the shell’s way of saying, “Clean up, kids, we’re going home.” And your precious long-running job will be unceremoniously terminated.

This is where nohup comes in. It’s the digital equivalent of giving your process a set of noise-canceling headphones and a “Do Not Disturb” sign. Its entire job is to tell a command, “Ignore that hangup signal. You stay here and keep working; I got this.”

How nohup Actually Works

The magic isn’t that complex. When you preface a command with nohup, it does two crucial things:

  1. It tells the process to ignore the SIGHUP signal. The process sets its signal handler for SIGHUP to SIG_IGN (ignore). It’s a one-line change in the process’s configuration, but it makes all the difference.
  2. It automatically handles output redirection. A process that ignores SIGHUP will keep running, but if it tries to write to the standard output or standard error (your terminal) after you’ve logged out, it’ll get a nasty error and likely crash. nohup prevents this by gently redirecting those streams to a file for you.

Let’s see it in action. The simplest form is:

nohup ./my-long-script.sh &

That & is important—it backgrounds the job immediately so you get your shell prompt back. The moment you hit enter, nohup gets to work. You’ll see something like:

nohup: ignoring input and appending output to 'nohup.out'

And just like that, your job is immune to your shell’s existential crises. Go ahead, log out. It’ll keep running.

The All-Important nohup.out File

See that message? nohup, in its infinite, minimalist wisdom, by default redirects both stdout and stderr and appends it to a file named nohup.out in the current directory. This is its one and only choice of filename. It’s not a configurable masterpiece; it’s a blunt instrument.

This leads to the first classic nohup pitfall: what if you run multiple nohup commands from the same directory? They will all blindly append their output to the same nohup.out file. The result is an interleaved, unparseable mess that looks like two people yelling different stories into the same voicemail.

The solution is to manually manage your output redirection. This is a best practice you should adopt immediately.

nohup ./my-script.sh > /var/log/my-script.log 2>&1 &

Let’s break that down:

  • > /var/log/my-script.log: Redirects standard output to a specific, sensible log file.
  • 2>&1: This means “redirect file descriptor 2 (stderr) to wherever file descriptor 1 (stdout) is currently going.” So both stdout and stderr go to the same log file. If you want them separate, you can do 2> error.log.

This gives you clean, predictable logging and avoids the nohup.out pile-up.

nohup’s Quirks and Limitations

nohup is a brilliant old tool, but it has some rough edges. It’s our job to acknowledge them.

  • It’s Not a Session Manager. This is the big one. nohup protects the process from SIGHUP, but it doesn’t magically re-parent it to init (PID 1) like a proper daemon. If your process is sensitive to its parent dying (e.g., it’s a shell script that might try to communicate with the shell that started it), you might see odd behavior. For truly robust backgrounding, nohup is often just the first step paired with disown (a shell builtin that removes the job from the shell’s job table) or better yet, a full terminal multiplexer like tmux.
  • Input is Ignored. The message says “ignoring input” for a reason. If your script prompts a user for input, it will immediately hit an end-of-file and likely fail. nohup is only for non-interactive, fire-and-forget commands.
  • The nohup.out Default. We’ve already covered this, but it bears repeating: relying on the default nohup.out is for amateurs. Be explicit.

The nohup && disown One-Two Punch

So you started a job without nohup and suddenly realize you need to log out. Panic? Nah. Your shell probably has you covered with disown.

First, background the running job if it’s not already: press Ctrl+Z to suspend it, then type bg to resume it in the background. Or, if it’s already running, just use bg.

Then, use the disown command to sever the tie between the job and your shell.

$ ./massive-job.sh
# ...oops, I need to leave. Ctrl+Z to suspend.
[1]+  Stopped                 ./massive-job.sh
$ bg
[1]+ ./massive-job.sh &
$ disown %1

Now that job is no longer on your shell’s guest list and won’t receive the SIGHUP. You can combine this with nohup for a belt-and-suspenders approach: start with nohup, background it, and then disown it to be extra sure. It’s a bit redundant, but it works.

In the end, nohup is a venerable and incredibly useful tool. It’s the quickest way to make a process stubborn enough to survive your departure. Just remember its limitations, always manage your own logging, and know that for truly complex operations, you’ll eventually want to graduate to a tool like tmux or systemd services. But for a quick fix? nohup is your old reliable friend.