【问题标题】:Execute commands on fish of WSL via subprocess通过子进程对 WSL 的鱼执行命令
【发布时间】:2021-10-15 15:03:28
【问题描述】:

我已经安装了 WSL(Ubuntu),现在我想从 WSL 访问鱼并从中执行类似 date 的命令。我该怎么做?

这是我的尝试!

import subprocess
subprocess.run(["wsl", "fish"], shell=True)
subprocess.run(["date"], shell=True)

输出显示执行到代码的第 2 行,而不是在 fish 终端中执行 date 命令。有什么解决办法吗?

【问题讨论】:

  • 你是从 Windows Python 还是 WSL 运行它?
  • 我正在使用 Windows python。

标签: python subprocess windows-subsystem-for-linux


【解决方案1】:

假设您只想捕获输出,最有效的调用应该是:

cp = subprocess.run(["wsl", "-e", "date"], capture_output=True)
date = cp.stdout

通过指定-e,您完全跳过了shell,从而避免了shell 启动的开销。

如果你真的想强制它在fish 内运行:

cp = subprocess.run(["wsl", "-e", "fish", "-c", "date"], capture_output=True)
date = cp.stdout

更多细节:

如果fish 是您的默认shell,那么您真的不需要将它指定为wsl 命令的参数。您可以通过在 PowerShell 或 CMD 中尝试以下操作来看到这一点:

wsl ps -eH
  PID TTY          TIME CMD
    1 ?        00:00:00 init
   21 ?        00:00:00   init
   22 ?        00:00:00     init
   23 pts/0    00:00:00       fish
   30 pts/0    00:00:00         ps

请注意,ps 命令虽然在 WSL 命令行上不带 fish 运行,但仍然在默认 shell 下运行。

但是,您没有必须。如果命令不需要 shell,您可以通过以下方式直接运行它而无需通过 shell(避免开销):

wsl -e ps -ef
  PID TTY          TIME CMD
    1 ?        00:00:00 init
   11 ?        00:00:00   init
   12 ?        00:00:00     init
   13 pts/0    00:00:00       ps

您会注意到没有任何 shell 正在运行。这是我在上面用 Python 中的 ["wsl","-e","date"] 推荐的变体。

假设 fish 不是您的默认 shell,但您确实希望它运行。

wsl -e fish -c "ps -eH"
  PID TTY          TIME CMD
    1 ?        00:00:00 init
   20 ?        00:00:00   init
   21 ?        00:00:00     init
   22 pts/0    00:00:00       fish
   29 pts/0    00:00:00         ps

但不要使用wsl fish "ps -eH"(或wsl fish -c date)。那会鱼中之火,非常浪费:

   PID TTY          TIME CMD
    1 ?        00:00:00 init
   11 ?        00:00:00   init
   12 ?        00:00:00     init
   13 pts/0    00:00:00       fish
   20 pts/0    00:00:00         fish
   22 pts/0    00:00:00           ps

【讨论】:

    【解决方案2】:

    使用您的命令,第一个 subprocess.run() 启动一个进程,然后等待它完成。如您所知,wsl fish 实际上并没有自行完成,这意味着您的 python 应用程序现在将无限期阻塞。

    你真正想做的是启动一个进程,通过它的 STDIN 向它发送数据,然后读取它的 STDOUT 输出。

    但你不能完全这样做——因为 1,你不想阻塞解释器!

    proc = Popen(["wsl", "fish"], stdin=PIPE, stdout=PIPE, stderr=PIPE)
    output, err = proc.communicate(b"date")
    print(output)
    

    communicate 也会阻塞。如果你想保持这个运行你会做proc.stdin.write() 然后proc.stdout.readline()

    【讨论】:

      【解决方案3】:

      第一个 subprocess.run 将启动一个交互式鱼壳。

      只有当你键入 exit 时,date 才会运行。

      【讨论】:

        猜你喜欢
        • 2018-11-12
        • 1970-01-01
        • 2021-09-08
        • 2014-03-25
        • 2014-02-12
        • 1970-01-01
        • 2012-01-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多