Running a bash background process on Windows 10 without an open terminal

Update

Microsoft has addressed this. Background / daemon processes are now allowed to continue running even after bash.exe (or other WSL launcher process) is closed. A recent build of Win10 (spring 2018 for public releases, build 17046 or greater) is required.

The below is preserved for posterity.


Sadly/absurdly, there is no way to do this. Microsoft, in their infinite wisdom, have decided that WSL (Windows Subsystem for Linux) will only run while you have a bash.exe process open. Close the last one (or possibly even close the last window; I'm not sure if it'll tolerate being run headless) and WSL shuts down, killing all of its processes.

The justification for this was "to conserve resources", which is absurd on several different levels but most notably because, dammit, my computer has those resources and they are there to be used! If I want a process to run, it should run; if I don't want it to run, I can kill it. For something explicitly intended as a developer tool, it sometimes feels like WSL is only usable as a plaything and its users can't be trusted to know what they're doing.

Anyhow, if you want this fixed, vote for Consider enabling cron jobs, daemons and background tasks on the UserVoice page. It's currently the second-most-voted-for request, and is "on the backlog".


A recent addition to WSL allows for starting wsl commands directly from the 'run' or Start menu. You can append an ampersand to the command (normal shell behavior), which results in a momentary bash terminal which immediately disappears but the command continues.

Examples, within Start » Run:

wsl sleep 20 &
wsl python -c 'import time; time.sleep(20);' &

If you go into Windows' Task Manager, it will show a Sleep or Python2 command running for 20 seconds, then self-clearing.

One thing I've found is that environment variables are not available. For instance, DISPLAY, if set in the windows normal method, is not passed to WSL. For this, there needs to be a way to pass these variables. Even if the command does not support setting the needed variable via a command line argument, it's possible to do it using bash itself:

# direct, command-dependent
wsl emacs --display=:0 &

# indirect, more flexible
wsl bash -c "DISPLAY=:0 emacs" &

NB: I'm currently running win10_64, Version 1709 (OS Build 16299.64).


Yeah, it's "impossible" at the moment.

But it's possible to have it "appear" like a background process with some trickery. I wanted this functionality pretty bad myself so after a couple of hours I came up with a shitty but working solution.

The main point is to create an invisible shell that you launch WSL Bash to with VBScript. You can then have that script be run on startup. Proper Task Scheduling didn't work for some strange reason.

Linux side to enable daemons you can have your own rudimentary startup system that abuses .bashrc for example.

The process is detailed here in this document I wrote https://emil.fi/bashwin. I didn't implement task monitoring but it should be pretty easy to extend.