回答golang中的密码shell提示

时间:2017-05-12 17:49:41

标签: linux git go

我正在寻找一种方法来回答golang中的shell密码提示。

喜欢:

bussiere@kus:~/Workspace/rteest$ ./passwordtest.sh
Password : 

我想在启动shell命令/脚本后在golang中使用我的令牌自动输入密码......

我已经制作了一些脚本,如果一切正常(在golang中),可以使用mfa获得一次性令牌。所以我需要输入临时令牌到linux密码提示符。

我知道有expect命令但是我想编译我的程序来嵌入它并且具有最小的依赖性。

谢谢和问候

编辑到@nevermore我已经尝试过了(但它不起作用):https://play.golang.org/p/Ffm3q5h636

package main

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

func main() {
    cmdb := "git"
    args := "clone https://bb@gitlab.com/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

编辑bis:

    cmdb := "git"
    args := "https://bb@gitlab.com/bb/fzgs.git"
cmd := exec.Command(cmdb, "clone", args)

它要求输入密码:

&{39; https://bb@gitlab.com':

的密码

2 个答案:

答案 0 :(得分:4)

问题是你试图在Git问你之前发送密码 这样做。

Git要求输入密码的方式取决于是否设置了credential帮助程序。如果未设置凭证帮助程序,或者未返回密码,则会要求用户输入。

解决方案#1:在URI中包含密码

在大多数情况下(至少使用Github和Bitbucket)Git服务器接受 通过HTTPS URI传递的凭证,例如https://user:password@domain.com/repo.git

cmd := exec.Command("git", "clone", "https://bb:PASSWORD@gitlab.com/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:自定义凭证助手

另一种方法是制作凭证助手脚本,例如:

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

并通过GIT_ASKPASS传递:

cmd := exec.Command("git", "clone", "https://bb@gitlab.com/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()

答案 1 :(得分:2)

如果要求用户在其shell中输入密码,则可以使用golang 写入os.Stdin 的io.Writer

Properly passing data on stdin to a command and receiving data from stdout of that command in golang

os.Stdin 是由

创建的os.File
NewFile(uintptr(syscall.Stdin), "/dev/stdin"

密码提示将从此文件中读取

您可以在问题中执行./passwordtest.sh,然后将密码写入os.Stdin,bash脚本应接受golang写入的字节作为密码。

或者实际上是exec类型的Cmd包中的方法。

  1. 使用 cmd 执行shell脚本
  2. 使用 stdin cmd.StdinPip()
  3. 输入密码
  4. 使用cmd.CombinedOutput()
  5. 阅读shell 输出
      

    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's standard input")
    }()
    
    out, err := cmd.CombinedOutput()
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("%s\n", out)
    
      

    StdinPipe返回一个管道,该命令将在命令启动时连接到命令的标准输入。 Wait看到命令退出后,管道将自动关闭。呼叫者只需要调用关闭以强制管道更快关闭。例如,如果正在运行的命令在标准输入关闭之前不会退出,则调用者必须关闭管道。

    此外,您的cmd参数不应该与克隆和网址相结合,请改为使用

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