我在 Windows 上使用 PowerShell 和 WSL“Ubuntu 20.04 LTS”。我没有本机 Linux 发行版,并且由于嵌套设备原因,我无法使用虚拟化。
我的目的是在 PowerShell 中使用 Windows Python 脚本调用 WSL 将一些 avd 快照解密为原始图像。我已经尝试过
os.popen
、subprocess.Popen
/run
/call
、win32com.client
、multiprocessing
等
我可以启动 WSL shell,但没有进一步的命令传递给它。有人知道如何让 shell 成为焦点并准备更多说明吗?
代码示例:
from multiprocessing import Process
import win32com.client
import time, os, subprocess
def wsl_shell():
shell = win32com.client.Dispatch("wscript.shell")
shell.SendKeys("Start-Process -FilePath C:\\Programme\\WindowsApps\\CanonicalGroupLimited.Ubuntu20.04onWindows_2004.2021.825.0_x64__79rhkp1fndgsc\\ubuntu2004.exe {ENTER}")
time.sleep(5)
os.popen("ls -l")
if __name__ == '__main__':
ps = Process(target = wsl_shell)
ps.start()
有几种从 Windows Python 运行 WSL 脚本/命令的方法,但基于
SendKeys
的方法通常是最后的手段,恕我直言,因为它是:
此外,请避免使用
ubuntu2004.exe
(或者,对于发现此问题的其他用户,请避免使用已弃用的 bash.exe
命令)。您正在寻找功能更强大的 wsl.exe
命令。它有很多用于运行命令的选项,而<distroname>.exe
版本缺乏。
考虑到这一点,这里有一些简化的例子:
os.system
import os
os.system('wsl ~ -e sh -c "ls -l > filelist.txt"')
在 Windows Python 中运行此代码后,进入您的 Ubuntu WSL 实例,您应该在主目录中找到
filelist.txt
。
这有效是因为:
os.system
可用于启动 wsl
命令~
告诉 WSL 在用户的主目录中启动(更具确定性,同时能够避免在这种情况下指定每个路径)wsl -e sh
在 WSL 中运行 POSIX shell(您也可以使用 bash
来实现)-c "<command(s)>"
传递给 shell 在 WSL shell 中运行这些命令鉴于此,您几乎可以从 Windows Python 运行任何 Linux 命令。对于多个命令:
用分号分隔它们。例如:
os.system('wsl ~ -e sh -c "ls -l > filelist.txt; gzip filelist.txt')
或者更好,只需将它们全部放入 WSL 中的脚本中(使用 shebang 行),将其设置为可执行文件,然后通过以下方式运行脚本:
wsl -e /path/to/script.sh
这甚至可能是一个 Linux Python 脚本(假设脚本中的 shebang 行正确):
wsl -e /path/to/script.py
因此,如果需要,您甚至可以通过这种方式从 Windows Python 调用 Linux Python。
subprocess.run
os.system
语法非常适合“即发即忘”脚本,您不需要在 Python 中处理结果,但通常您需要捕获 WSL/Linux 命令的输出以便在 Python 中处理。
为此,请使用
subprocess.run
:
import subprocess
cp = subprocess.run(["wsl", "~", "-e", "ls", "-l"], capture_output=True)
print(cp.stdout)
和以前一样,
-e
参数可以是您想要的任何类型的 Linux 脚本。
请注意,
subprocess.run
还提供命令的退出状态。