在同一个shell中运行多个Exec命令的方法(使用golang)

10

我遇到了使用os/exec包运行多个命令的困难。我在网上和stackoverflow上搜寻了很久,但没有找到适合我的解决方案。这是我的源代码:

package main

import (
    _ "bufio"
    _ "bytes"
    _ "errors"
    "fmt"
    "log"
    "os"
    "os/exec"
    "path/filepath"
)

func main() {
    ffmpegFolderName := "ffmpeg-2.8.4"
    path, err := filepath.Abs("")
    if err != nil {
        fmt.Println("Error locating absulte file paths")
        os.Exit(1)
    }

    folderPath := filepath.Join(path, ffmpegFolderName)

    _, err2 := folderExists(folderPath)
    if err2 != nil {
        fmt.Println("The folder: %s either does not exist or is not in the same directory as make.go", folderPath)
        os.Exit(1)
    }
    cd := exec.Command("cd", folderPath)
    config := exec.Command("./configure", "--disable-yasm")
    build := exec.Command("make")

    cd_err := cd.Start()
    if cd_err != nil {
        log.Fatal(cd_err)
    }
    log.Printf("Waiting for command to finish...")
    cd_err = cd.Wait()
    log.Printf("Command finished with error: %v", cd_err)

    start_err := config.Start()
    if start_err != nil {
        log.Fatal(start_err)
    }
    log.Printf("Waiting for command to finish...")
    start_err = config.Wait()
    log.Printf("Command finished with error: %v", start_err)

    build_err := build.Start()
    if build_err != nil {
        log.Fatal(build_err)
    }
    log.Printf("Waiting for command to finish...")
    build_err = build.Wait()
    log.Printf("Command finished with error: %v", build_err)

}

func folderExists(path string) (bool, error) {
    _, err := os.Stat(path)
    if err == nil {
        return true, nil
    }
    if os.IsNotExist(err) {
        return false, nil
    }
    return true, err
}

我想执行像在终端中一样的命令。cd path; ./configure; make。所以我需要按顺序运行每个命令,并在最后一个命令完成后等待再移动到下一个命令。我的代码当前版本显示:./configure: no such file or directory 我认为这是因为cd path命令在新的shell中执行,而不是在上一个命令之前保持相同目录,有什么建议吗? 更新:我通过更改工作目录,然后执行./configure和make命令来解决了问题。

err = os.Chdir(folderPath)
    if err != nil {
        fmt.Println("File Path Could not be changed")
        os.Exit(1)
    }

我仍然好奇是否有一种方法可以在同一个Shell中执行命令。

1个回答

41
如果您想在一个单独的shell实例中运行多个命令,您将需要使用类似于以下内容的内容调用shell:
cmd := exec.Command("/bin/sh", "-c", "command1; command2; command3; ...")
err := cmd.Run()

这将使shell解释给定的命令。 它还允许您执行shell内置命令,例如cd。 请注意,在安全方式下替换用户数据以使用这些命令可能并不容易。

如果您只想在特定目录中运行命令,可以不使用shell来执行。 您可以将当前工作目录设置为执行以下命令:

config := exec.Command("./configure", "--disable-yasm")
config.Dir = folderPath
build := exec.Command("make")
build.Dir = folderPath

...然后继续像以前一样进行下去。


谢谢您的回答。我特别感谢您的第一个建议。我偶然发现了您的第二个建议,目前正在使用它。 - reticentroot
@James 我尝试了你建议的方法。 command := exec.Command("echo *tar.gz | xargs -n1 tar zxf") command.Dir = pathFinal cmdErr := command.Run() 然而这对我不起作用, command := "cd "+pathFinal+"; "+"echo *tar.gz | xargs -n1 tar zxf" cmd := exec.Command("/bin/sh", "-c", command) 这个可以工作。我想用第一种方式实现它。我不知道为什么它不起作用。 - supriya
它抛出错误: 无法解压文件:exec:“echo *tar.gz | xargs -n1 tar zxf”:$PATH中找不到可执行文件 - supriya
1
@globs和pipes是shell功能,而不是由内核解释的东西。您需要从Go中执行这些部分,或者显式调用shell并让它为您解释事物。您可以通过第一个命令的StdoutPipe()将命令管道连接到第二个命令的Stdin - James Henstridge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接