回答golang中的密码shell提示

use*_*794 12 linux git go

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

喜欢 :

bussiere@kus:~/Workspace/rteest$ ./passwordtest.sh
Password : 
Run Code Online (Sandbox Code Playgroud)

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

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

我知道有期望命令,但我想编译我的程序嵌入它并具有最小的依赖性.

感谢致敬

编辑到@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)

}
Run Code Online (Sandbox Code Playgroud)

它给了我这个:

2017/05/12 20:42:36 exit status 1
exit status 1
Run Code Online (Sandbox Code Playgroud)

编辑之二:

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

它要求输入密码:

" https://bb@gitlab.com "的密码:

Rus*_*nov 5

问题是您试图在 Git 要求您发送密码之前发送密码。

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

解决方案 #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()
Run Code Online (Sandbox Code Playgroud)

解决方案#2:自定义凭证助手

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

#!/bin/bash -
printf '%s\n' 'YOUR_PASSWORD'
Run Code Online (Sandbox Code Playgroud)

并通过它传递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()
Run Code Online (Sandbox Code Playgroud)


Nev*_*ore 4

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

在 golang 中正确地将 stdin 上的数据传递给命令并从该命令的 stdout 接收数据

os.Stdin是一个os.File创建者

NewFile(uintptr(syscall.Stdin), "/dev/stdin")
Run Code Online (Sandbox Code Playgroud)

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

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


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

  1. 使用cmd执行 shell 脚本
  2. 使用stdin输入密码,或者cmd.StdinPip()
  3. 使用以下命令读取 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's standard input")
}()

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

fmt.Printf("%s\n", out)
Run Code Online (Sandbox Code Playgroud)

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

另外,你的cmd参数不应该结合克隆和网址,而是尝试

cmd := exec.Command(cmdb, "clone", url)
Run Code Online (Sandbox Code Playgroud)