139

Just switched from bash to zsh.

In bash, background tasks continue running when the shell exits. For example here, dolphin continues running after the exit:

$ dolphin .
^Z
[1]+  Stopped                 dolphin .
$ bg
[1]+ dolphin . &
$ exit

This is what I want as the default behavior.

In contrast, zsh's behavior is to warn about running jobs on exit, then close them if you exit again. For example here, dolphin is closed when the second exit-command actually exits the shell:

 % dolphin .
^Z
zsh: suspended  dolphin .
 % bg
[1]  + continued  dolphin .
 % exit
zsh: you have running jobs.
 % exit 

How do I make zsh's default behavior here like bash's?

Owen_AR
  • 2,867
  • 5
  • 20
  • 23

4 Answers4

244

Start the program with &!:

dolphin &!

The &! (or equivalently, &|) is a zsh-specific shortcut to both background and disown the process, such that exiting the shell will leave it running.

Bruno Duyé
  • 1,014
  • 11
  • 13
  • 6
    For completeness, can you also list how to disown it once it is already started? – trusktr May 14 '19 at 21:09
  • 1
    @trusktr [There's a different question about disowning the foreground process](https://stackoverflow.com/q/625409/777586). I think it's best kept separate for clarity. For anyone interested in zsh specifically, I've asked [a question on U&L SE about how to create a faster workflow for disowning the foreground process](https://unix.stackexchange.com/q/223432/16404). – Anko - inactive in protest May 15 '19 at 14:24
  • I like this solution and I'll implement it for individual commands, but I'm still looking for a way to change Zsh's default behavior. – Vince Sep 10 '20 at 04:18
  • 5
    @Vince Do you mean changing the default to always disown backgrounded processes? If so, you can do that with `setopt nohup` in your `~/.zshrc`. Then starting a command backgrounded with `&` will also always disown it. Though by default zsh will still remind you that you have running jobs when you attempt to exit. You can turn that off too with `setopt nocheckjobs`. – Anko - inactive in protest Sep 10 '20 at 10:12
  • @Anko I think `setopt nocheckjobs` does what I want. Now I've found the available options in `man zshoptions`. I'd like to turn off the warning. I know when I have background processes and I don't need it. I'd like it to close background processes unless I started them with `nohup`. I currently use this with a shell function that runs [PyCharm](https://www.jetbrains.com/pycharm/) in the background with `nohup`. When I type `pycharm .` it runs `nohup charm $@ &`. It doesn't close when I close the terminal, but I still get that warning and have to type `exit` twice. – Vince Sep 10 '20 at 22:57
  • Why doesn't this work when inside an alias? – DimiDak May 06 '21 at 22:30
  • @DimiDak Works fine for me. `alias z="chromium &|"` – Anko - inactive in protest May 06 '21 at 23:34
  • @Anko I forgot to mention my alias contains also sudo. So maybe that's the reason. – DimiDak May 06 '21 at 23:39
  • 1
    @DimiDak Also works fine for me. `alias z="sudo sleep 1 &|"`. Construct minimal examples like this, and you'll narrow it down eventually. – Anko - inactive in protest May 07 '21 at 00:22
  • @Anko , well it doesn't work for some reason. If I use sudo for some other command first, then it works. Also why pipe and not exclamation mark as the answer suggests? – DimiDak May 07 '21 at 01:16
67

From the zsh documentation:

HUP

... In zsh, if you have a background job running when the shell exits, the shell will assume you want that to be killed; in this case it is sent a particular signal called SIGHUP... If you often start jobs that should go on even when the shell has exited, then you can set the option NO_HUP, and background jobs will be left alone.

So just set the NO_HUP option:

% setopt NO_HUP
Community
  • 1
  • 1
Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • If you don't want the warning, yes. – Carl Norum Oct 10 '13 at 18:18
  • Despite what the documentation says, this still kills the job for whatever reason. Tested on zsh 5.8: start an infinite loop-sleep script as a process, press ctrl+Z, run setopt, exit, and the process is killed. – Jeff Hykin Jan 24 '22 at 03:56
44

I have found that using a combination of nohup, &, and disown works for me, as I don't want to permanently cause jobs to run when the shell has exited.

nohup <command> & disown

While just & has worked for me in bash, I found when using only nohup, &, or disown on running commands, like a script that calls a java run command, the process would still stop when the shell is exited.

  • nohup makes the command ignore NOHUP and SIGHUP signals from the shell
  • & makes the process run in the background in a subterminal
  • disown followed by an argument (the index of the job number in your jobs list) prevents the shell from sending a SIGHUP signal to child processes. Using disown without an argument causes it to default to the most recent job.

I found the nohup and disown information at this page, and the & information in this SO answer.

Update

When I originally wrote this, I was using it for data processing scripts/programs. For those kinds of use cases, something like ts (task-spooler), works nicely.

ryanjdillon
  • 17,658
  • 9
  • 85
  • 110
9

I typically use screen for keeping background jobs running.

1) Create a screen session:

screen -S myScreenName

2) Launch your scripts,services,daemons or whatever

3) Exit (detach) screen-session with

screen -d

or shortcut ALT+A then d


After few hundreds of years - if you want to resume your session (reattach):

screen -r myScreenName

If you want to know if there's a screen-session, its name and its status (attached or detached):

screen -ls

This solution works on all terminal interpreters like bash, zsh etc. See also man screen

Aydin K.
  • 3,309
  • 36
  • 44
  • 1
    A note for MacOS users, the keyboard shortcut to detach from screen was Control+A, then D. Also this was my only option when I left a process running and yielding to stdout, writing screen -d there wouldn't help. – Bishoy Jan 25 '20 at 00:39
  • 1
    Nice but nothing to do with the Q which is specifically about how to keep bg tasks running when exiting ZSH. – RichieHH Oct 25 '20 at 16:46
  • 1
    @RichieHH I don't believe you are correct. You can spawn "background tasks" and allow them to run when exiting ZSH: `screen -d -m your command` will spawn a screen session for `your command`, and a following `exit` will exit the shell. – kevr Jul 13 '21 at 23:47
  • 1
    Needs more upvotes – Riveascore Dec 04 '21 at 01:26