microsoft / WSL

Issues found on WSL
https://docs.microsoft.com/windows/wsl
MIT License
17.43k stars 822 forks source link

Cron will not keep running in background and does not log to cron.log #9072

Closed aagha closed 3 months ago

aagha commented 2 years ago

Version

Microsoft Windows [Version 10.0.22621.675]

WSL Version

Kernel Version

Linux version 5.15.68.1-microsoft-standard-WSL2 (oe-user@oe-host) (x86_64-msft-linux-gcc (GCC) 9.3.0, GNU ld (GNU Binutils) 2.34.0.20200220) #1 SMP Mon Sep 19 19:14:52 UTC 2022

Distro Version

Ubuntu 20.04

Other Software

No response

Repro Steps

Note: /etc/wsl.conf contains the following:

[boot] command = service cron start

  1. Start a terminal
  2. Add the following in cron to run every minute:

* * * * * echo "Cron test at $(date +\%k:\%M)" >> /home/(you account)/crontest.txt 2>&1

  1. Restart cron: sudo service cron restart
  2. Wait a few min and verify output to crontest.txt
  3. Close the terminal
  4. Ensure the Ubuntu instance is shut down in PowerShell w: wsl -l -v
  5. Wait a few minutes (since the cron output is happening every minute)
  6. Restart a new terminal
  7. Check crontest.txt: There are no entries from the time the terminal was closed [0]
  8. No entries of cron running/log output in /var/log/cron.log [1]

Expected Behavior

0 - Expecting cron to be running in the background 1 - Expect there to be output in /var/log/cron.log every time cron runs

Once the terminal is closed, cron does not continue to run in the background. How do you keep cron running in the background in the following conditions:

  1. Starting windows without opening a terminal
  2. Opening a terminal and then closing it

Related: If you setup a Task Scheduler event to start the WSL cron service on bootup (documented here), the cron does not run automatically.

Actual Behavior

  1. After closing the terminal, cron does not run.
  2. There is no output to /var/log/cron.log

Diagnostic Logs

No response

cerebrate commented 2 years ago

This is #8854; as documented, systemd services won't keep a WSL instance alive, only processes which are children of the Microsoft init. Thus cron running without a terminal won't do it.

The current workaround for this is to create a process that runs forever and detach it from the calling terminal such that it will persist (as a child of the init) even when the terminal is closed. So you can create a script, call it wait-forever.sh:

#!/bin/sh
while true
do
  sleep 1h
done

then run it with

nohup wait-forever.sh > /dev/null &

and then when you exit the terminal that script will keep running as a child of init, and that will keep the instance open.

(Make sure you don't run it inside a tmux session or anything else that might kill its children in ways nohup won't stop.)

aagha commented 2 years ago

Thanks @cerebrate

Is there a way to have this be executed by the Task Scheduler so it never needs to be called from the terminal and will execute on computer boot-up?

Any ideas on why there's no cron logging happening to cron.log?

cerebrate commented 2 years ago

On the former, you could put the nohup line in a script of its own, then call that from Task Scheduler. Computer boot-up won't work, because WSL has to run inside a user session, but you could have it be executed on user log-on, instead, which should work. I haven't tested it myself, but there's no reason it wouldn't.

On the latter, hrm, it's been a while since I used a non-systemd system (so my cron logs end up with systemd-journald), but doesn't crond log through syslog, in which case you'd need rsyslogd running to get logging?

aagha commented 2 years ago

If systemd isn't running, nor is rsyslogd.

Got any pointers to setup systemd on Ubuntu? I wonder why this isn't the case out of the box.

cerebrate commented 2 years ago

Alas, I'm not familiar with how to set things up without systemd these days. ☹️

NotTheDr01ds commented 2 years ago

Pretty much a duplicate of #8661 that I opened before learning this was intentional (so I closed it).

Currently, the easiest way to keep WSL running is to start a service that runs directly under a user-initiated init. I know that's weird phrasing, but it's the best I can describe it.

As a practical example. Simply:

sudo apt install keychain
sudo -e /etc/profile.d/keep_wsl_running.sh

Add the following to this file:

#!/usr/bin/env sh
eval $(keychain -q)

See this Ask Ubuntu answer where I cover the "why this is needed" and "how the workaround works" in (excruciating) detail.

With that in place, running WSL one-time with Bash or Zsh as a login-shell will:

NotTheDr01ds commented 2 years ago

Got any pointers to setup systemd on Ubuntu?

See either the Blog announcement or a Stack Overflow Community Wiki Answer I created on the topic.

I wonder why this isn't the case out of the box.

As the blog post says:

Given that this changes how WSL behaves when booting up, we wanted to be careful about applying this to user’s already existing WSL distros. So currently you need to opt-in to enable systemd for a specific WSL distro, and we will monitor feedback and investigate making this behavior by default in the future.

Personally, I prefer Systemd not be enabled most of the time. It's nice to be able run a wsl ls -lah in PowerShell (or any other simple command) without starting up dozens of other processes.

aagha commented 2 years ago

@NotTheDr01ds Thanks for the response.

A couple of questions. You write:

With that in place, running WSL one-time with Bash or Zsh as a login-shell will:

Can you clarify what you melan a login-shell? I want my cron service to run automatically without having to open a terminal. Do you mean that if I don't have systemd running, then from the task scheduler, I can call: wsl.exe -e /etc/profile.d/keep_wsl_running.sh (without nohup)?

Start any services in your [boot] command

~Do you mean in /etc/wsl.conf?~ <- I see from your Ask Ubuntu post that's what you mean.

ghost commented 2 years ago

Currently: If you properly daemonize a process it should keep the distro alive. If you don't daemonize correctly all bets are off.

Example: https://linux.die.net/man/1/daemonize

xiaoqidun commented 1 year ago

Windows Subsystem for Linux Keep Daemon:https://github.com/xiaoqidun/wslkd

RickKohrs commented 1 year ago

On the former, you could put the nohup line in a script of its own, then call that from Task Scheduler. Computer boot-up won't work, because WSL has to run inside a user session, but you could have it be executed on user log-on, instead, which should work. I haven't tested it myself, but there's no reason it wouldn't.

nohup was not working for me, so I found a workaround 1) create a batch file perpetual-bash.bat with the following: wsl.exe sudo setsid /wait-forever.sh (see above comments about wait-forever.sh) 2) Create a shortcut to perpetual-bash.bat 3) Add the shortcut file in to the windows start-up folder.

jangrewe commented 1 year ago

For anybody coming across this, you can now just use systemd: https://devblogs.microsoft.com/commandline/systemd-support-is-now-available-in-wsl/

microsoft-github-policy-service[bot] commented 3 months ago

This issue has been automatically closed since it has not had any activity for the past year. If you're still experiencing this issue please re-file this as a new issue or feature request.

Thank you!