2015-03-15 4 views
0

У меня есть довольно простой вопрос о голанге.Учитывая произвольную строку, как я могу выполнить команду bash?

Для произвольной строки, такой как "echo foo", или "CGO_ENABLED=0 go build -o ./bin/echo -a main.go", что такое идиоматический способ разбора/выполнения этой команды с использованием os/exec?

Способ, которым я получил эту работу, кажется довольно взломанным, и я ищу более идиоматический подход.

userInput = "CGO_ENABLED=0 go build -o ./bin/echo -a main.go" 
command := exec.Command("/bin/bash", "-c", userInput) 
out, err := command.Output() 
if err != nil { 
    fmt.Println(err) 
} 
+0

Если у вас нет правильных правил цитирования, то вам нужно что-то вроде 'f: = strings.Fields (x)' then 'os.Exec'' exec.Command (f [0], f [1:]. ..) 'должен работать. –

+1

Кстати, ваш пример называет переменную «userInput» ... никогда не пропускает пользовательский ввод непосредственно в оболочку (или иначе «запускает» ее), не выполняя строгую проверку/санитарию, если вам не нравится предоставлять полные разрешения текущих процессов кому-либо, кто может обеспечить его ввод. –

ответ

0

В зависимости от того, насколько произвольно и гибких вашей userInput строки, я мог бы сделать что-то вроде этого.

package main 

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

func main() { 
    if err := os.Setenv("FOO", "bar"); err != nil { 
     log.Println(err) 
    } 

    // As Dave C pointed out, exec.Command does this for you. 
    // goAbsPath, err := exec.LookPath("go") 
    // if err != nil { 
    // log.Println(err) 
    // } 

    // Pass whatever other arguments necessary. 
    cmd := exec.Command("go", "version") 
    if err = cmd.Run(); err != nil { 
     log.Println(err) 
    } 
} 

Если ничего другого, может быть os.Setenv и exec.LookPath может быть полезно знать.

+1

Зачем напрямую гадать с 'LookPath'? Разве вы не читали документацию ['exec.Command'] (https://golang.org/pkg/os/exec/#Command), которая четко заявляет, что она сделает это для вас, когда потребуется? –

+0

Кроме того, существует разница между передачей новой среды только * ребенку (с помощью команды «cmd.Env») и установкой среды текущих процессов (которая по умолчанию будет наследоваться всеми будущими дочерними процессами) с 'os.Setenv'. –

+0

Спасибо, Дэйв С. Нет, я не читал документацию 'exec.Command'. – 425nesp

0

Я могу написать так:

cmd := exec.Command(cmdName, arg1, arg2, ..) 
cmd.Env = append(cmd.Env, "foo=bar") 

err = cmd.Start() 
if err != nil { 
    // log or something else 
} 

err = cmd.Wait() 
if err != nil { 
    if exitErr, ok := err.(*exec.ExitError); ok { 
     if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { 
      // handle err according to different status.ExitStatus() 
     } 
     // ... 
    } 
    // ... 
} 
// ... 

Godoc объясняет очень хорошо, если вам нужно больше информации.

Смежные вопросы