Выполнение команды из строки с параметрами в go - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь выполнить команду с помощью go. Команда в строке.

package main

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

    "github.com/davecgh/go-spew/spew"
)

func main() {
    commandToRun := `echo $HOME`

    log.Printf("Running %s\n", commandToRun)

    args := strings.Fields(commandToRun)
    spew.Dump(args[1:len(args)])
    command := exec.Command(args[0], args[1:len(args)]...)
    command.Stdout = os.Stdout
    command.Stdin = os.Stdin
    command.Stderr = os.Stderr
    err := command.Run()

    if err != nil {
        log.Printf("Command finished with error: %v", err)
    }
}

Вывод:

2018/11/14 09:41:22 Running echo $HOME
([]string) (len=1 cap=1) {
 (string) (len=5) "$HOME"
}
$HOME

Что бы я хотел иметь:

2018/11/14 09:41:22 Running echo $HOME
([]string) (len=1 cap=1) {
 (string) (len=5) "$HOME"
}
/home/whatever

Похоже, что go как-то дезинфицирует строку. Таким образом, $HOME не расширяется. Есть ли способ запустить строку точно так, как если бы она была введена в оболочку?

Это важная часть. В идеале я хотел бы перейти от строки к тексту в текущей оболочке.

РЕДАКТИРОВАТЬ: Пример ниже решает простейший сценарий, но не охватывает "запуск строки точно так, как если бы она была набрана в оболочке".

Если я переключусь на expandenv:

commandToRun := os.ExpandEnv(`echo "$HOME"`)

Я получаю:

2018/11/14 11:45:44 Running echo "/Users/rafael"
([]string) (len=1 cap=1) {
 (string) (len=15) "\"/home/whatever\""
}
"/home/whatever"

В оболочке я получу:

$ > echo "$HOME"
/home/whatever

без кавычек.

Это близко к тому, что я хочу, но не совсем так.

Ответы [ 3 ]

0 голосов
/ 14 ноября 2018

Перед выполнением команды вы можете активно развернуть все переменные env в строке, используя os.ExpandEnv:

os.ExpandEnv("echo $HOME")

Из документов :

ExpandEnv заменяет $ {var} или $ var в строке в соответствии со значениями текущих переменных среды.Ссылки на неопределенные переменные заменяются пустой строкой.

0 голосов
/ 14 ноября 2018

Если вы хотите получить вывод $ echo $HOME, минимальный код, который вам нужен, это

fmt.Println(os.Getenv("HOME"))

Больше ничего не нужно.

  • Если вы используете os.ExpandEnv("echo $HOME"), затем сначала будет раскрыто $HOME var, а затем будет выдана строка типа echo /home/<user>
  • . Если вы используете command := exec.Command("echo", os.Getenv("HOME")), то она будет разрешена как command := exec.Command("echo", "/home/<user>") и, наконец, будет выдавать результат/home/<user>
  • Если вы используете

    commandToRun := os.ExpandEnv("echo $HOME") command := exec.Command(strings.Fields(commandToRun)...)

    , тогда он будет обрабатываться как предыдущие случаи.

Так что лучше использовать только fmt.Println(os.Getenv("HOME")).

0 голосов
/ 14 ноября 2018

$HOME (и все другие переменные env) расширяются оболочкой.Вы не запускаете оболочку, поэтому они не раскрываются.

Вам нужно искать переменную env непосредственно в go, что-то вроде:

command := exec.Command("echo", os.Getenv("HOME"))

или вот так:

commandToRun := os.ExpandEnv("echo $HOME")
command := exec.Command(strings.Fields(commandToRun)...)

Обратите внимание, что этот последний подход не будет работать, если $HOME расширяется до строки, содержащей пробелы, поэтому метод os.Getenv, как правило, безопаснее / предпочтительнее для этого варианта использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...