从 Windows Python 脚本将命令传递到 WSL Shell

问题描述 投票:0回答:1

我在 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()
python windows-subsystem-for-linux
1个回答
6
投票

有几种从 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
还提供命令的退出状态。

© www.soinside.com 2019 - 2024. All rights reserved.