如何从 Go 更快地调用 Powershell?

Tom*_*ime 7 powershell go

用 Go 编写的程序通过 shell 执行 PowerShell 来完成某些任务。这很慢,因为每次调用都会exec.Command()启动 PowerShell,运行一个命令,然后退出。我们正在运行数百个命令,并且启动 PowerShell 数百次是一个很大的开销。

如果提前知道命令,我们可以简单地生成 powershell 脚本并执行它。然而,需要运行的命令是动态生成的,因此这对我们不起作用。

这是我们用来运行的代码command

  out, err := exec.Command("powershell", "-NoProfile", command).CombinedOutput()
  if err != nil {
    // ...
  }
Run Code Online (Sandbox Code Playgroud)

是否可以启动一次 PowerShell 并为其提供单独的命令?

更新:有人问我正在运行哪些 PS 命令。有些是:

  • Get-DnsServerResourceRecord -ComputerName FOO -ZoneName BAR
  • Remove-DnsServerResourceRecord -Force -ComputerName "FOO" -ZoneName "BAR" -Name "X" -RRType "Y" -RecordData "Z"
  • Add-DnsServerResourceRecordX-ComputerName FOO -ZoneName BAR ...

2022-03-09 更新:我很不好意思地说,我发现了缓慢问题,而且这并不是我提出问题时所假设的。正在运行的 PowerShell 命令偶尔会获取需要很长时间才能处理的庞大数据集。所以,问题根本不在于 Go 或 exec!也就是说,这个问题对于想要批量命令的人来说仍然有用。

小智 6

您可以使用Cmd.StdinPipe

package main

import (
   "fmt"
   "log"
   "os/exec"
)

func main() {
   cmd := exec.Command("powershell", "-nologo", "-noprofile")
   stdin, err := cmd.StdinPipe()
   if err != nil {
      log.Fatal(err)
   }
   go func() {
      defer stdin.Close()
      fmt.Fprintln(stdin, "New-Item a.txt")
      fmt.Fprintln(stdin, "New-Item b.txt")
   }()
   out, err := cmd.CombinedOutput()
   if err != nil {
      log.Fatal(err)
   }
   fmt.Printf("%s\n", out)
}
Run Code Online (Sandbox Code Playgroud)

虽然,这是一个奇怪的请求,因为对于某些工作来说,Go 应该几乎能够完成 PowerShell 可以做的任何事情,包括进行 Syscalls