先决条件

先决条件

每当我执行时git push,我都必须在提示符下手动输入用户名和密码。
但是,我想自动执行此过程。

因此,我尝试使用管道将凭据传递给命令:

printf 'username\npassword' | git push

但输入用户名和密码的提示仍然没有消失!
为什么它不起作用?

笔记:
我知道这可以通过以下方式完成: 但我感兴趣的是知道管道方法有什么问题?
git push 'https://username:[email protected]/username/repo.git'


另外,为了确认此过程适用于其他情况,我做了一个实验。
我创建了一个脚本b.py

b.py

#!/usr/bin/env python3

username = input()
password = input()

log = open("log.txt", "w")
print(username + "\n" + password, file=log)

printf 'abcd\nefgh' | ./b.py然后,我在终端中 执行,它确实按预期工作,并生成包含用户名和密码字符串的日志文件:

log.txt

abcd
efgh

答案1

按照您的示例,这仅适用于顺序提示是脚本的直接部分的情况。但是,如果git您的值在任何用户名/密码提示之前被传递给进程 - 可能是在进程执行所有操作(网络等)之前GIT_ASKPASS- 供参考: https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables

答案2

先决条件

前段时间,GitHub 停止接受密码,而是要求用户创建令牌。当然,我记不住令牌,但我也不想将其作为纯文本存储在 中.git-credentials。此外,我也不想将其作为参数传递(有人可以读取/proc.bash_history找到它!)。我编写了一个简单的加密器来使用密码加密令牌,但就像你一样,无法将解密的令牌传输到管道,git并在寻找解决方案时发现了这个问题。不幸的是,我没有在这里找到答案。然而,我很幸运地找到了一个不相关的问题,这让我找到了答案。答案是脚本

解决方案

我们可以使用它script创建一个自动会话并将凭据传递给它。这是我为其编写的脚本:

#!/bin/bash

read -p "Password: " -s password
echo
token=$(echo "$password" | decrypt_token) || exit $?
cmd="git push $@"
echo -e "username\n$token" | script -E never -c "$cmd" /dev/null

-E never表示我不希望我的凭据被回显(打印在终端中)。我将其用作/dev/null日志文件,因为我不关心日志记录。

重要的提示: echo是我的 shell 中的一个内置命令,这意味着可以安全地将密码和令牌作为参数传递给它。如果它是外部程序,有人可能会从中读取参数/proc。我建议您检查用于管道的命令是否内置在 shell 中。如果找不到合适的内置命令,请使用带有 heredoc 的 cat:

token=$(
  (
  cat <<EOF
$password
EOF
  ) | decrypt_token
)

第2部分

将我的设置复制到不同的机器后,我遇到了一个奇怪的错误:

fatal: could not read Password for 'https://[email protected]': Success

我检查了gitscreen与原始机器上的版本是否相同,但未能找到根本原因。然而,此评论 可能提供提示:

getpass() tries too hard to find the real terminal

作为一种解决方法,我创建了一个单独的脚本GIT_ASKPASS(我觉得这是一个更清晰的解决方案)。

这是更改后的主要脚本:

#!/bin/bash

if ! tty -s; then
  echo "Can't operate without tty."
  exit 1
fi

TTY=$(tty) GIT_USERNAME=username GIT_ASKPASS=~/git-creds git push $@

这是git-creds

#!/bin/bash

if echo "$1" | grep -q '^Password'; then
  read -p "Password: " -s password < $TTY
  echo "$password" | decrypt_token
  # put a newline to separate prompt and output
  echo > $TTY
else
  echo "$GIT_USERNAME"
fi

它直接从您的 TTY 读取密码并将解密的令牌提供给 git。对于用户名,它只会回显 GIT_USERNAME 环境变量。

也可以添加这些行.bashrc(或任何替代行):

export TTY=$(tty)
export GIT_USERNAME=username
export GIT_ASKPASS=~/git-creds

而且您不需要命令的包装器。

相关内容