如何将动态参数传递给Go的exec.Command命令?

huangapple go评论82阅读模式
英文:

How could I pass a dynamic set of arguments to Go's command exec.Command?

问题

我在这里遇到了一个关于将参数传递给Go的exec.Command函数的问题,我想知道是否有一种动态传递这些参数的方法?以下是来自sed问题的示例代码:

package main

import "os/exec"

func main() {
    app := "echo"
    //app := "buah"

    arg0 := "-e"
    arg1 := "Hello world"
    arg2 := "\n\tfrom"
    arg3 := "golang"

    cmd := exec.Command(app, arg0, arg1, arg2, arg3)
    out, err := cmd.Output()

    if err != nil {
        println(err.Error())
        return
    }

    print(string(out))
}

如你所见,每个参数都在上面定义为arg0arg1arg2arg3。它们与要运行的实际命令一起传递给Command函数,这里是app变量。

如果我有一个参数数组,其数量可能是不确定的,我想要传递这些参数,这是否可行?

英文:

I came across a question on here relating to arguments being passed to Go's exec.Command function, and I was wondering if there was a way do pass these arguments dynamically? Here's some sample code from sed question:

package main

import "os/exec"

func main() {
    app := "echo"
    //app := "buah"

    arg0 := "-e"
    arg1 := "Hello world"
    arg2 := "\n\tfrom"
    arg3 := "golang"

    cmd := exec.Command(app, arg0, arg1, arg2, arg3)
    out, err := cmd.Output()

    if err != nil {
        println(err.Error())
        return
    }

    print(string(out))
}

So as you can see each arg is defined above as arg0, arg1, arg2 and arg3. They are passed into the Command function along with the actual command to run, in this case, the app var.

What if I had an array of arguments that always perhaps had an indeterministic count that I wanted to pass through. Is this possible?

答案1

得分: 97

像这样:

args := []string{"你", "喜欢", "什么", "就", "用什么"}
cmd := exec.Command(app, args...)

在 golang.org 上查看有关语言和教程的内容。

英文:

Like this:

args := []string{"what", "ever", "you", "like"}
cmd := exec.Command(app, args...)

Have a look at the language and tutorial on golang.org.

答案2

得分: 0

你可以尝试使用flag库,这对我很有效。这是一个不同的示例,但它使用了接受动态参数的概念。

package main

import (
	"flag"
	"log"
	"os/exec"
	"strings"
)

func main() {
	flag.Parse()
	arg1, arg2 := strings.Join(flag.Args()[:1], " "), strings.Join(flag.Args()[1:], " ")
	cmd := exec.Command(arg1, arg2)
	err := cmd.Start()
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("等待命令完成...")
	log.Printf("进程ID为 %v", cmd.Process.Pid)
	err = cmd.Wait()
	log.Printf("命令完成并出错,现在重新启动:%v", err)
}

然后像这样运行:

$ go run main.go node ../web-test/index.js
2019/01/26 13:32:29 等待命令完成...
2019/01/26 13:32:29 进程ID为 3582
英文:

You can try with the flag library, which has worked for me. This is a different example but it uses the concept of accepting dynamic arguments.

package main

import (
	"flag"
	"log"
	"os/exec"
	"strings"
)
func main() {
    	flag.Parse()	
    	arg1, arg2 := strings.Join(flag.Args()[:1], " "), strings.Join(flag.Args()[1:], " ")
    	cmd := exec.Command(arg1, arg2)
    	err := cmd.Start()
    	if err != nil {
    		log.Fatal(err)
    	}
    	log.Printf("Waiting for command to finish...")
    	log.Printf("Process id is %v", cmd.Process.Pid)
    	err = cmd.Wait()
    	log.Printf("Command finished with error, now restarting: %v", err)
}

And running like this

$ go run main.go node ../web-test/index.js
2019/01/26 13:32:29 Waiting for command to finish...
2019/01/26 13:32:29 Process id is 3582

答案3

得分: -1

有两种方法:

  1. 命令行标志
  2. 使用配置文件。程序将读取该文件并进行一些初始化操作或获取一些参数等。

配置文件示例

// manifest.json
{
  "name": "xxx",
  "version": "0.0.0",
  "server": {
    "port": 8080
  }
}

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "os"
)

var (
    Config Settings
)

type Settings struct {
    Name    string `json:"name"`
    Version string `json:"version"`
    Server  Server `json:"server"`
}

type Server struct {
    Port int `json:"port"`
}

func LoadConfig(path string, settings *Settings) {
    jsonFile, err := os.Open(path)
    if err != nil {
        fmt.Printf(`无法打开文件 "%s": %v`, path, err)
    }

    manifestBytes, _ := ioutil.ReadAll(jsonFile)
    if err := json.Unmarshal(manifestBytes, &settings); err != nil {
        fmt.Printf("无法将JSON解组为结构体(Settings): %v", err)
    }
}

func main() {
    LoadConfig("manifest.json", &Config)
    paras := []string{Config.Version, fmt.Sprintf("%d", Config.Server.Port)}
    print(paras)
    // cmd := exec.Command(Config.Name, paras...)
    // ...
}
英文:

There have two ways,

  1. command-line-flags
  2. use the config file. The program will read this file and do some initialize or get some parameters etc.

Example of the config file.

// manifest.json
{
  "name": "xxx",
  "version": "0.0.0",
  "server": {
    "port": 8080
  }
}

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "os"
)

var (
    Config Settings
)

type Settings struct {
    Name    string `json:"name"`
    Version string `json:"version"`
    Server  Server `json:"server"`
}

type Server struct {
    Port int `json:"port"`
}

func LoadConfig(path string, settings *Settings) {
    jsonFile, err := os.Open(path)
    if err != nil {
        fmt.Printf(`Unable to open the "%s": %v`, path, err)
    }

    manifestBytes, _ := ioutil.ReadAll(jsonFile)
    if err := json.Unmarshal(manifestBytes, &settings); err != nil {
        fmt.Printf("Unable to unmarshal json to struct (Settings): %v", err)
    }
}

func main() {
    LoadConfig("manifest.json", &Config)
    paras := []string{Config.Version, fmt.Sprintf("%d", Config.Server.Port)}
    print(paras)
    // cmd := exec.Command(Config.Name, paras...)
    // ...
}

huangapple
  • 本文由 发表于 2014年4月1日 17:30:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/22781788.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定