How do I disown/detach a process from the Git Bash terminal that come with Git's Windows installer?

I would like to run commands from the terminal (mostly Python servers) and essentially daemonize them. I am running the MinGW terminal "Git Bash" that comes with the Windows installer for Git.

Things tried that do not work:

  • nohup -> command not found
  • setsid -> command not found
  • $ script.py & -> does not behave as expected
  • $ script.py & disown -> does not behave as expected

I would use bg, but my end-goal is to close the terminal after my servers are all running and not kill the processes.


Solution 1:

This is a synthesis from my longer answer to a similar question in SO.

If your app logs to stdout/stderr, use:

cmd //c start cmd //k  "path\\to\\script-dir\\script.py"

If it logs to files, via sockets etc. and you do not need stdout/stderr, use:

cmd //c start //D "path\\to\\script-dir" script.py

In both cases you get a daemon like process which will survive when you close bash. In the first instance your script is hosted in a visible cmd.exe window.

Much more here.

Solution 2:

Simply prefix your command with start.

E.g.

start TortoiseGitProc /command:showcompare /revision1:master /revision2:HEAD

The spawned process inherits the current working directory.

Solution 3:

The mixture of cmd and start does work, although both of @antonio 's solutions were "visible" for me. I was trying to find another way, more consistent with MinGW.

TL;DR

mintty bash -mc "commands &>/dev/null < /dev/null &" seems to always work


I'm not sure what has all changed since this original post, but using 2.31.1 now, and run git for window's bash in a few different ways.

A subset of what I tried

Here are my results

  1. In mintty (the "normal" way)

    • Stdin on mintty is a pipe rather than a tty and would require winpty in order to get a tty (no idea if this matters)

    I would execute these commands, then close mintty

    Command Works?
    git gui Nope, the command git is called here, and hooked in, so closing she shell kill the git command
    git-gui Works, although this is not calling the CLI git anymore, but the windows GUI executable directly, git-gui. This is not a general solution
    sleep 60 Nope
    sleep 60& Only if you press Ctrl+D to close, instead of click the X or pressing Alt+F4
    bash -c "sleep 60&" Yes (Still get a warning when you close mintty, but it doesn't kill sleep)
    mintty bash -c "sleep 60&" Nope
    mintty bash -mc "sleep 60&" Yes, fully detached
    ./foo.bat& Nope, foo.bat uses stdout, needs to be redirected
    ./foo.bat < /dev/null& Only if you press Ctrl+D to close, instead of click the X or pressing Alt+F4
    mintty bash -mc "./foo.bat < /dev/null&" Yes, fully detached
    winpty bash -mc "./foo.bat&" Nope, when stdin is close, the pty dies
    winpty bash -c "./foo.bat&" < /dev/null Does not work the first time, works on additional calls
    winpty bash -mc "./foo.bat&" < /dev/null Only works like half the time, random
    winpty bash -c "./foo.bat" < /dev/null & Only works like half the time, random
    /c/Python39/python foo.py Same result as sleep/foo.bat
  2. In PowerShell

    • Running in powershell does gives stdin a tty

    Showing different results only

    Command Works?
    sleep 60& Nope
    bash -c "sleep 60&" Nope
    ./foo.bat < /dev/null& Nope
    mintty bash -mc "./foo.bat < /dev/null&" Nope
    mintty bash -mc "./foo.bat &> /dev/null < /dev/null&" Yes
    winpty bash -c "./foo.bat&" < /dev/null Nope
    winpty bash -c "./foo.bat&" &> /dev/null < /dev/null Works half the time, even the first time
    winpty bash -mc "./foo.bat&" < /dev/null Nope
    winpty bash -mc "./foo.bat&" &> /dev/null < /dev/null Works half the time
    winpty bash -mc "./foo.bat" &> /dev/null < /dev/null & Works half the time

Main difference: First three lines don't work, and stdout/stderr had to be redirected. Which is interesting in the case where a new mintty is spawned.

  1. In Command Prompt (cmd)

    • Running in cmd does gives stdin a tty
    • Results same as PowerShell
  2. In Windows Terminal

    • Running in W Terminal does gives stdin a tty
    • Results same as PowerShell

What's going on here

  • I was attempting to detach stdin/stdout/stderr/and tty

  • Some of my earlier tests got TTY to say ? in ps, however that did not help

  • Based off of the observations with start/cmd, I was able to get a combo that used mintty. I imagine this will handle more cases when it comes to nested quotes, as this keeps the call within the GNU arguments arena, should the need arise.

  • It took me a while to find the winpty/redirect/bg combo that worked, then I found out that if I try it 10 times in a row, it might work 3 times, it might work 8 times, but usually not 10. It's completely unstable

    • I could now find out why, even using:

      for s in seq 10; do winpty bash -c './foo.bat &> foo.$$' < /dev/null; done

    • Not all 10 foo.# files even existed, telling me the bash command didn't even start to get executed.

    • winpty executes additional path translation on arguments inconsistent with MinGW's path translations rules, so using winpty is generally asking for trouble

  • disown in bash on MinGW appears to do nothing for or against this endeavor.

Solution 4:

I have no idea if this will work in bash in Windows, but bash provides a built-in command to "disown" a background process. After you've backgrounded the job with bg just run disown. By default it will disown the most recently bg-ed job, but you can also give it a job number if you have multiple background jobs.

More info here on Job control built-ins.