从 Python 脚本向 WSL Shell 传递命令
Passing Commands to the WSL Shell from a Python Script
我正在 Windows 使用 PowerShell 和 WSL 'Ubuntu 20.04 LTS'。我没有原生的 Linux Distro,而且由于嵌套设备的原因我无法使用虚拟化。
我的目的是在 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()
从WindowsPython运行宁WSL scripts/commands有几种方法,但基于SendKeys
的方法通常是最后的选择,恕我直言,因为它是:
- 经常non-deterministic
- 缺少任何控制逻辑
另外,避免ubuntu2004.exe
。功能更强大的 wsl.exe
命令正是您要找的。 <distroname>.exe
版本缺少 运行ning 命令的 很多 选项。
考虑到这一点,这里有一些简化的例子:
使用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
还提供了命令的退出状态。
我正在 Windows 使用 PowerShell 和 WSL 'Ubuntu 20.04 LTS'。我没有原生的 Linux Distro,而且由于嵌套设备的原因我无法使用虚拟化。
我的目的是在 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()
从WindowsPython运行宁WSL scripts/commands有几种方法,但基于SendKeys
的方法通常是最后的选择,恕我直言,因为它是:
- 经常non-deterministic
- 缺少任何控制逻辑
另外,避免ubuntu2004.exe
。功能更强大的 wsl.exe
命令正是您要找的。 <distroname>.exe
版本缺少 运行ning 命令的 很多 选项。
考虑到这一点,这里有一些简化的例子:
使用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
还提供了命令的退出状态。