Run Multiple Exec Commands in the same shell golang

20,080

If you want to run multiple commands within a single shell instance, you will need to invoke the shell with something like this:

cmd := exec.Command("/bin/sh", "-c", "command1; command2; command3; ...")
err := cmd.Run()

This will get the shell to interpret the given commands. It will also let you execute shell builtins like cd. Note that this can be non-trivial to substitute in user data to these commands in a safe way.

If instead you just want to run a command in a particular directory, you can do that without the shell. You can set the current working directory to execute the command like so:

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

... and continue on like you were before.

Share:
20,080
reticentroot
Author by

reticentroot

VP of Programmatic Engineering At Timehop/Nimbus

Updated on June 16, 2020

Comments

  • reticentroot
    reticentroot almost 4 years

    I'm having trouble figuring out how to run multiple commands using the os/exec package. I've trolled the net and stackoverflow and haven't found anything that works for me case. Here's my source:

    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
    }
    

    I want to the command like I would from terminal. cd path; ./configure; make So I need run each command in order and wait for the last command to finish before moving on. With my current version of the code it currently says that ./configure: no such file or directory I assume that is because cd path executes and in a new shell ./configure executes, instead of being in the same directory from the previous command. Any ideas? UPDATE I solved the issue by changing the working directory and then executing the ./configure and make command

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

    Still now i'm curious to know if there is a way to execute commands in the same shell.