![更新](https://linux22.com/image/1518762/%E6%9B%B4%E6%96%B0.png)
在 Windows 10 上编程时,我通常使用 linux 子系统,因此我的所有路径都与 相关~
。我有一个 python 脚本,它会在后台永远运行,直到我终止该进程。在没有打开终端的情况下,我该如何在 Windows 10 bash 上执行此操作?
我尝试过的事情:
bash -c "python3 script.py
来自 Run。nohup python3 -u script.py
然后关闭终端。setsid python3 script.py
然后关闭终端。
这些都不起作用。有办法吗?或者,如果我从 W10 和 bash 运行脚本,而不必每次都切换它们,那么有没有办法改变路径,使它们正常工作?
答案1
WSL 最近新增了一项功能,允许直接从“运行”或“开始”菜单启动 wsl 命令。您可以在命令后附加一个 & 符号(正常的 shell 行为),这样会产生一个瞬时bash
终端,它会立即消失,但命令会继续执行。
例如,在开始运行:
wsl sleep 20 &
wsl python -c 'import time; time.sleep(20);' &
如果您进入 Windows 的任务管理器,它将显示Sleep
或Python2
命令运行 20 秒,然后自行清除。
我发现的一件事是环境变量不可用。例如,DISPLAY
如果在 Windows 常规方法中设置,则不会传递给 WSL。为此,需要有一种方法来传递这些变量。即使命令不支持通过命令行参数设置所需的变量,也可以使用其bash
自身来执行此操作:
# direct, command-dependent
wsl emacs --display=:0 &
# indirect, more flexible
wsl bash -c "DISPLAY=:0 emacs" &
注意:我目前正在运行 win10_64,版本 1709(OS Build 16299.64)。
答案2
更新
微软已经解决了这个问题。现在允许后台/守护进程在bash.exe
(或其他 WSL 启动器进程)关闭后继续运行。需要最新版本的 Win10(2018 年春季公开发布,版本 17046 或更高版本)。
以下内容为后人保留。
可悲/荒谬的是,没有办法做到这一点。微软凭借其无限的智慧,决定 WSL(适用于 Linux 的 Windows 子系统)仅在您打开进程时运行bash.exe
。关闭最后一个(或可能甚至关闭最后一个窗户;我不确定它是否能容忍无头运行)并且 WSL 关闭,终止其所有进程。
这样做的理由是“为了节省资源”,这在很多层面上都是荒谬的,但最明显的是,该死的,我的电脑有这些资源,它们就是用来使用的!如果我想运行一个进程,它就应该运行;如果我不想让它运行,我可以杀死它。对于明确用作开发人员工具的东西,有时感觉 WSL 只能用作玩物,不能相信它的用户知道他们在做什么。
无论如何,如果你想解决这个问题,请投票考虑启用 cron 作业、守护进程和后台任务在UserVoice 页面。这是目前获得投票第二多的请求,并且“处于积压状态”。
答案3
是的,目前是“不可能”的。
但通过一些小技巧,可以让它“出现”为后台进程。我自己也非常想要这个功能,所以几个小时后我想出了一个虽然糟糕但可行的解决方案。
重点是创建一个不可见的 shell,使用 VBScript 将 WSL Bash 启动到该 shell。然后,您可以在启动时运行该脚本。由于某些奇怪的原因,正确的任务调度不起作用。
Linux 端启用守护进程您可以拥有自己的基本启动系统,例如滥用 .bashrc。
这个过程在我写的这篇文档中有详细说明https://emil.fi/bashwin。我没有实现任务监控,但它应该很容易扩展。
答案4
我花了很长时间才找到一种非常复杂的方法(从批处理文件中):
start bash -c "DISPLAY=:0 [command] & (sleep 0.5 && kill -n 9 $$)"
下面详细说明一下它的作用和原因:
- `start`:使批处理文件窗口消失
- `bash -c`:让你运行 bash 命令
- `DISPLAY=:0`:设置你的 X 服务器
- `[command]`:你的命令(`[command && [command]`)
- `&`:使下一个命令在其后运行开始而不是当它完毕
- `sleep 0.5`:确保进程已启动
- `&&`:使下一个命令在执行后运行完毕而不是当开始
- `kill -n 9 $$`:终止 bash shell,使其只剩下图形应用程序
注意:
DISPLAY=:0
将其设置为 处的 x-server:0
。要将其更改为(例如):1
,请执行DISPLAY=:1
等。注意:
start
仅当来自批处理脚本时才需要。如果来自终端,则不需要这个注意:
sleep
每个应用程序需要不同的设置。你甚至可能需要省略它。