I have a script (on Windows) that sets a number of environment variables. I would like to execute this script in Go to set up environment variables for subsequent calls to a binary.
Something like this:
cmd1 := exec.Command("setup_env.bat")
cmd.Run()
// other_command.exe relies on environment variables
// set by setup_env.bat
cmd2 := exec.Command("some_binary.exe")
cmd2.Env = cmd1.Env
cmd2.Run()
However this doesn't work, as cmd1.Env
is empty after calling cmd1.Run()
(environment variables set in cmd1
don't seem to propagate to cmd1.Env
). os.Environ()
also seems unaffected after calling cmd1.Run()
.
If you're curious as to why I'm doing this, I'm trying to automate a task that normally requires the user to call setup_env.bat
followed by other_command.exe
in a command prompt. I do not own setup_env.bat
, and it may change frequently, so I can't just set the environment variables myself in Go.
I managed to produce the desired result with the following code:
cmd := exec.Command("setup_env.bat", "&&", "some_binary.exe")
cmd.Run()
I also discovered it's possible to manually parse the environment variables by capturing stdout
after printing the environment with SET
. For example:
func getEnv(command string) ([]string, error) {
cmd := exec.Command(command, "&&", "SET")
out, _ := cmd.StdoutPipe()
err := cmd.Start()
if err != nil {
return nil, err
}
rawEnv, _ := ioutil.ReadAll(out)
err = cmd.Wait()
if err != nil {
return nil, err
}
env := strings.Split(string(rawEnv), "
")
return env[:len(env)-1], nil
}
// ...
cmd := exec.Command("some_binary.exe")
env, err := getEnv("setup_env.bat")
if err != nil {
log.Fatal(err)
}
cmd.Env = env // or os.Setenv(...) if you need it in current context
cmd.Run()