繁体   English   中英

Go exec.Command pipe output 进入另一个 Z2F2D399F0EA88447359FE5514B3

[英]Go exec.Command pipe output into another powershell

我是 Go 的新手,我遇到了以下问题。 我需要使用 os.exec 与 powershell 交互并捕获 output 中的每个命令/管道。

例如,我有以下命令

powershell /C cat somefile.md | Select-String -Pattern someinput

我需要第一个命令的 output

powershell /C cat somefile.md

和 pipe 的 output

powershell /C Select-String -Pattern someinput

下面的代码在 linux 和 cmd 在 Windows 上工作正常,我必须使用 Z2F2D399F0EA8847859FEZ51B34...

编辑:经过进一步调查,我得出结论,无论出于何种原因, Select-String和其他 powershell 特定命令都不能通过管道传输。 是因为 powershell 需要 PSObject 作为输入吗?

那是我现在乱七八糟的代码:

func executeCmds{
    //save all exec.Commands in one array (I've no clue how many cmds there are later)
    var cmdList []exec.Cmds 

    cmdList = append(cmdList, *exec.Command("powershell", "/C", "cat somefile.md"))

    //*****EDIT*****//

    // not working $Input is missing
    cmdList = append(cmdList, *exec.Command("powershell", "/C", "Select-String -Pattern someinput"))

    // working command $Input is important
    cmdList = append(cmdList, exec.Command("powershell", "/C", "$Input | Select-String -Pattern someinput"))

    // this is performance wise NOT an option!
    // cmdList = append(cmdList, *exec.Command("powershell", "/C", "cat somefile.md | Select-String -Pattern someinput"))
    
    // save the latest stdout into tmp to stdin the next command (works fine on linux and cmd.exe)
    var tmp []byte

    for i, s := range cmdList {
        if i > 0 {
            s.Stdin = strings.NewReader(string(tmp)) //this does not work, powershell somehow can't use Stdin
        }

        stdout, err := s.CombinedOutput()
        tmp = stdout

        if err != nil {
            o := fmt.Sprint(err) + ": " + string(stdout)
            err = errors.New(o)
            panic(err)
            break
        }

        // Print the output
        fmt.Println(string(stdout))
    }
}

您不需要为此使用 PowerShell,您可以直接使用 Go :

package main
import "golang.org/x/sys/windows/registry"

func main() {
   a, e := registry.CURRENT_USER.ReadSubKeyNames(0)
   if e != nil {
      panic(e)
   }
   for _, s := range a {
      println(s)
   }
}

https://pkg.go.dev/golang.org/x/sys/windows/registry

如果您需要通过 go 应用程序传递数据,那么您可以执行以下操作(我不确定这将如何提高使用 powershell 管道的性能):

package main

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

func main() {
    // save all exec.Commands in one array (I've no clue how many cmds there are later)
    var cmdList []*exec.Cmd

    cmdList = append(cmdList, exec.Command("powershell", "/C", "cat somefile.md"))
    cmdList = append(cmdList, exec.Command("powershell", "/C", "$Input | Select-String -Pattern someinput"))

    var tmp []byte
    for i, s := range cmdList {
        if i > 0 { // Send the output of the previous command into the next command
            input, err := s.StdinPipe()
            if err != nil {
                panic(err)
            }
            go func(w io.WriteCloser, data []byte) {
                w.Write(data) // Should really check for errors here
                w.Close()
            }(input, tmp)
        }
        var err error
        tmp, err = s.CombinedOutput() // As you are taking standard error here too you should check for errors
        if err != nil {
            panic(err)
        }
    }
    // Print the final output
    fmt.Println(string(tmp))
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM