是否可以在后台运行 WSL 应用程序?

是否可以在后台运行 WSL 应用程序?

我在 ubuntu 中使用 snap store 安装了 LXD,然后将其连接到 Windows 客户端,但为了能够从 Windows 运行容器,Ubuntu 应用程序必须打开。有没有办法让 LXD 服务器在后台运行,还是必须打开 Ubuntu 才能使其工作? wsl --status返回:

Default Distribution: Ubuntu
Default Version: 2

wsl --version返回:

WSL version: 0.70.0.0
Kernel version: 5.15.68.1
WSLg version: 1.0.45
MSRDC version: 1.2.3575
Direct3D version: 1.606.4
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.22000.1098

cmd /c ver返回:

Microsoft Windows [Version 10.0.22000.1098]

答案1

说实话伟大的问题,正如我在经历以下各种场景时意识到的那样。我不得不承认,WSL 在这里的工作方式令人困惑。在 WSL Github repo 上出现了许多与此相关的“问题”,但事实是这种行为是“设计使然”。

来自WSL/Systemd 公告

还要注意的是,有了这些更改,systemd 服务将不会让您的 WSL 实例保持活动状态。您的 WSL 实例将以与以前相同的方式保持活动状态,您可以(在此处阅读更多信息)https://devblogs.microsoft.com/commandline/background-task-support-in-wsl/)。

换句话说,WSL 旨在在某些情况下终止 Ubuntu,但链接的帖子并没有清楚地说明这些场景到底是什么。为了更好地理解它们(以及 WSL 的行为方式),让我们从(至少)四种不同的方式开始,你可以在 WSL 上的 Ubuntu 上启动后台任务或服务(又名守护进程):

  1. 以交互方式,通过命令行本身或使用助手service。例如:

    sudo service cron start
    # or even
    sudo /usr/sbin/cron
    

    当然,这适用于任何版本的 WSL,但 SysVInitservice可能仅适用于某些发行版(例如 Ubuntu)和服务。

    (重要)请注意,在此目的中,在 shell 启动脚本中运行的命令被视为“交互式”命令。这将在我的最终(黑客式)解决方案中派上用场。

  2. 以交互方式,作为 shell 的后台任务。例如:

    nohup sleep 100000 &
    
  3. 在 Windows 11 下,你可以通过 在 WSL 启动时自动启动守护进程/etc/wsl.conf。例如:

    [boot]
    command = service cron start
    
  4. 从 WSL 0.67.6 开始,使用 Systemd。这可以以交互方式 ( sudo systemctl cron start)、通过/etc/systemd链接自动进行,或作为另一项服务的依赖项进行。例如

    sudo systemctl cron start
    

    请注意,一旦在 WSL 中启用,Snap 守护程序(snapd)就会通过 Systemd 自动启动。


考虑到这些情况,我们需要考虑什么时候WSL 将终止 Ubuntu。正如我所说,这很“令人困惑”。我希望我能想出一个总结性陈述来描述这种行为,但我很难做到。我能做的最好的就是举例说明:

概括

  1. 不会终止
  2. 不会终止
  3. 將终止
  4. 將终止

详细信息和示例

  1. 通过命令行交互启动的服务将阻止 WSL 终止 Ubuntu。我们可以通过以下方式证明这一点:

    • 暂时禁用 Systemd/etc/wsl.conf
    • 退出 Ubuntu
    • 启动 PowerShell
    • wsl --shutdown
    • 通过以下方式重新启动 Ubuntu wsl ~(如果需要,wsl ~ -d Ubuntu-22.04等等)
    • sudo service cron start
    • 退出 shell
    • 等待一分钟(默认情况下 25 秒就足够了)并检查wsl -l -vUbuntu 是否仍然处于跑步状态。
    • wsl -e ps axjff应该显示cron仍在运行,即使没有 shell 在运行。
  2. 通过命令行以交互方式启动的后台任务也将阻止 WSL 终止 Ubuntu。按照前面的示例:

    • 由于 Systemd 仍处于禁用状态,因此从 PowerShell 中,wsl --shutdown
    • 启动 Ubuntu(例如wsl ~
    • 跑步nohup sleep 100000 &
    • 再按Enter一次即可关闭nohup消息
    • 退出 shell/Ubuntu 返回 PowerShell。
    • 等待30秒到一分钟,wsl -l -v显示Ubuntu仍在运行。
    • wsl -e ps axjff应该显示sleep命令仍在运行,即使没有 shell 在运行。
  3. /etc/wsl.conf另一方面,通过 启动的服务/进程将不会防止 WSL 终止 Ubuntu。

    • 从上一个示例开始(Systemd 已禁用)

    • 在 Ubuntu 中,sudo -e /etc/wsl.conf添加以下内容:

      [boot]
      command = service cron start
      
    • 退出 Ubuntu,然后从 PowerShell 中wsl --shutdown

    • 通过以下方式重启 Ubuntuwsl ~

    • ps axjff表明它cron作为父进程之一的子进程运行/init

    • 退出 shell/Ubuntu

    • 30秒到一分钟后将wsl -l -v显示Ubuntu不再运行。它已被终止。

  4. 通过 Systemd 启动的服务/进程也将不是防止 WSL 终止 Ubuntu。演示(尽管你正在经历这种情况):

    • 编辑/etc/wsl.conf并重新启用 Systemd,同时禁用(注释掉或删除)command

    • 退出 Ubuntu

    • 在 PowerShell 中,wsl --shutdown

    • wsl ~启动 Ubuntu。

    • ps axjff将显示 Systemd 服务正在运行和/或启动。

    • 一分钟后:

      sudo systemctl stop cron
      sudo systemctl start cron
      

      显然,这会产生停止 cron 然后重新启动的效果。这里的重点是表明,即使我们明确地以交互方式启动cron,这不会阻止 WSL 终止 Ubuntu。

    • 退出 shell/Ubuntu

    • 30秒到一分钟后,wsl -l -v将显示Ubuntu已经已停止

    至于您的具体问题,由于lxd它只是一个 Snap,在由 Systemd 启动的容器化环境中运行,因此它也将被终止。好吧,真倒霉……

解决方案

希望有一个更永久的修复即将到来,因为其中一位 WSL 开发人员确实表示希望保持发行版运行

与此同时,一个解决方案(当然可能还有更多)是通过 shell 启动文件启动一个长时间运行的进程。就我而言,我通常运行keychain

Keychain 的一些特点使其在这种情况下能够很好地工作:

  • 它在默认的 Ubuntu 存储库中可用
  • 它已经启动了 的一个单例实例ssh-agent。换句话说,如果ssh-agent已经在运行,它将附加到它而不是启动一个新的。
  • 它可以安静运行,并且如果不添加任何按键则无需交互

要进行设置:

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

并添加以下内容:

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

此脚本:

  • 启动 shell 时运行(假设大多数 shell 都是如此,例如 Bash 和 Zsh)。请注意,如果您使用 Fish 作为 shell,它将不会运行。如果您(或任何未来的读者)确实想使用 Fish(或不处理的其他 shell /etc/profile.d),请单独提问如何处理这种情况。我确实有一个解决方案,但这个答案(像往常一样)已经够长了 ;-)。

  • 评估 的输出keychain,以便它找到任何现有的ssh-agent(如果不存在,则启动一个新的)并设置 shell 的环境变量来指向它。

  • -q就像你可能想象的那样,它只是keychain静静地运行,没有输出

运行ssh-agent(通过 启动/etc/profile.d) 将阻止 WSL 终止 Ubuntu 发行版/实例/容器。关闭终端窗口后,Ubuntu 将继续运行,并且您的lxd(以及 Snap 安装的其他守护程序/服务) 也将保持运行。

要让 Ubuntu 正常终止,只需删除 即可ssh-agent。这可以通过多种方式完成,包括:

keychain -k all

当然,确保以交互方式启动的进程也会消失。一旦满足该条件,WSL 将正常终止 Systemd 及其单元/服务。

这里有一个特殊情况,那就是如果你开始一个会话wsl -u root。在这种情况下,ssh-agent以 root 身份运行,并且您需要sudo keychain -k all

答案2

在 Windows 启动时运行此 vbs 脚本。只需将其放在 Windows 启动文件夹中 (crl+r -> shell:startup)

wsl-启动.vbs:

# change '<Distro>' to the distro name you are using.
set ws=wscript.CreateObject("wscript.shell")
ws.run "wsl -d <Distro>", 0

形式:https://github.com/microsoft/WSL/issues/8854#issuecomment-1421910739

此后,每次启动机器并登录时,它都会启动 wsl 并等待输入。wsl 实例将保持活动状态。

然后您可以使用 systemd 在后台运行您想要的任何内容。

如果你使用以下命令手动重启 wsl 实例,请记得再次运行 vbswsl -t <distro> / wsl --shutdown

相关内容