Ответ на приглашение оболочки пароля в golang

Я ищу способ ответить на приглашение пароля оболочки в golang.

like:

[email protected]:~/Workspace/rteest$ ./passwordtest.sh
Password : 

Я хотел бы ввести пароль автоматически с помощью своего токена в golang после запуска команды оболочки / script...

Я сделал несколько script, которые получают одноразовый токен с mfa, если все в порядке (в golang). Поэтому мне нужно ввести токен tempory в приглашение пароля linux.

Я знаю, что есть команда expect, но я хотел бы скомпилировать мою программу, чтобы вставить ее и иметь минимальный размер.

Спасибо и приветствую

изменить thks на @nevermore Я пробовал это (но он не работает): https://play.golang.org/p/Ffm3q5h636

package main

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

func main() {
    cmdb := "git"
    args := "clone https://[email protected]/bb/fzgs.git"
cmd := exec.Command(cmdb, args)
stdin, err := cmd.StdinPipe()
if err != nil {
log.Fatal(err)
}

go func() {
defer stdin.Close()
io.WriteString(stdin, "QSRDFGHJfZERTYU")
}()

out, err := cmd.CombinedOutput()
if err != nil {
log.Fatal(err)
}

fmt.Printf("%s\n", out)

}

это дает мне следующее:

2017/05/12 20:42:36 exit status 1
exit status 1

edit bis:

    cmdb := "git"
    args := "https://[email protected]/bb/fzgs.git"
cmd := exec.Command(cmdb, "clone", args)

он запрашивает пароль:

Пароль для https://[email protected] ':

Ответ 1

Проблема в том, что вы пытаетесь отправить пароль до того, как Git попросит вас для этого.

И способ Git запрашивать пароль зависит от того, установлен ли credential. Если помощник учетных данных не установлен или не возвращает пароль, пользователю предлагается ввести его.

Решение №1: включить пароль в URI

В большинстве случаев (по крайней мере, с Github и Bitbucket) сервер Git принимает учетные данные, переданные через URI HTTPS, например. https://user:[email protected]/repo.git.

cmd := exec.Command("git", "clone", "https://bb:[email protected]/bb/fzgs.git")

env := os.Environ()
env = append(env, "GIT_ASKPASS=")
cmd.Env = env

var out bytes.Buffer
cmd.Stdout = &out

err := cmd.Run()

Решение №2: Пользовательский помощник по учетным записям

Другой способ заключается в создании вспомогательного мандата script, например:

#!/bin/bash -
printf '%s\n' 'YOUR_PASSWORD'

и передать его через GIT_ASKPASS:

cmd := exec.Command("git", "clone", "https://[email protected]/bb/fzgs.git")

env := os.Environ()
env = append(env, "GIT_ASKPASS=/path/to/fzgs-askpass.sh")
cmd.Env = env

var out bytes.Buffer
cmd.Stdout = &out

err := cmd.Run()

Ответ 2

Если пользователю предлагается ввести пароль в своей оболочке, вы можете использовать golang для для записи в файл io.Writer, который os.Stdin

Правильно передавать данные на stdin в команду и получать данные из stdout этой команды в golang

os.Stdin - это os.File, созданный

NewFile(uintptr(syscall.Stdin), "/dev/stdin"

И подсказка пароля будет читать этот файл

Вы можете выполнить ./passwordtest.sh как в своем вопросе, а затем записать пароль в os.Stdin, а bash script должен принять байты, написанные golang в качестве пароля.


Альтернативно на самом деле это метод для этого в пакете exec для типа Cmd.

  • Используйте cmd для выполнения вашей оболочки script
  • Введите пароль с помощью stdin или cmd.StdinPip()
  • Считайте shell вывод с помощью cmd.CombinedOutput()

Cmd представляет собой внешнюю команду, которая готовится или запускается.

https://golang.org/pkg/os/exec/#Cmd.StdinPipe

cmd := exec.Command("cat")
stdin, err := cmd.StdinPipe()
if err != nil {
    log.Fatal(err)
}

go func() {
    defer stdin.Close()
    io.WriteString(stdin, "values written to stdin are passed to cmd standard input")
}()

out, err := cmd.CombinedOutput()
if err != nil {
    log.Fatal(err)
}

fmt.Printf("%s\n", out)

StdinPipe возвращает канал, который будет подключен к стандартным вводам команды при запуске команды. Труба будет закрыта автоматически после того, как Wait увидит выход команды. Вызывающему абоненту нужно только позвонить Закрыть, чтобы закрыть трубку раньше. Например, если выполняемая команда не будет завершена до тех пор, пока не будет закрыт стандартный вход, вызывающий абонент должен закрыть трубку.

Кроме того, ваши аргументы Cmd не должны сочетать клон и URL-адрес, вместо этого попробуйте

cmd := exec.Command(cmdb, "clone", url)