Pré-condições

Pré-condições

Sempre que executo git push, tenho que digitar meu nome de usuário e senha manualmente no prompt.
No entanto, quero automatizar esse processo.

Então, tentei passar as credenciais para o comando usando piping:

printf 'username\npassword' | git push

mas a solicitação de nome de usuário e senha ainda não desaparece!
Por que não está funcionando?

Observação:
Eu sei que isso pode ser feito usando: mas estou interessado em saber o que há de errado com o método de tubulação?
git push 'https://username:[email protected]/username/repo.git'


Além disso, para confirmar se esse processo funciona para outros casos, fiz um experimento.
Criei um script b.py:

b.py:

#!/usr/bin/env python3

username = input()
password = input()

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

Então, executei printf 'abcd\nefgh' | ./b.pyno terminal que funcionou conforme esperado e resultou no arquivo de log contendo as strings de nome de usuário e senha:

log.txt:

abcd
efgh

Responder1

Isso funcionaria apenas no caso de prompts sequenciais que são a parte imediata do script, conforme seu exemplo. No entanto, no caso de gitseus valores serem passados ​​​​para o processo antes de qualquer solicitação de nome de usuário/senha - provavelmente enquanto ele está fazendo tudo (rede, etc.) antes GIT_ASKPASS- Para referência: https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables

Responder2

Pré-condições

Há algum tempo, o GitHub parou de aceitar senhas e pediu aos usuários que criassem tokens. Claro, eu não conseguia lembrar o token, mas também não queria armazená-lo como texto simples no formato .git-credentials. Além disso, eu não queria passar isso como argumento (alguém pode ler /procou .bash_historyencontrar!). Escrevi meu criptografador simples para criptografar o token com uma senha, mas, assim como você, não consegui canalizar o token descriptografado gite encontrei esta pergunta enquanto procurava uma solução. Infelizmente, não encontrei a resposta aqui. No entanto, tive a sorte de encontrar perguntas não relacionadas que me levaram à resposta. E a resposta éroteiro.

Solução

Podemos usar scriptpara criar uma sessão automatizada e canalizar credenciais para ela. Este é o script que escrevi para isso:

#!/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 neverindica que não quero que minhas credenciais sejam repetidas (impressas no terminal). Estou usando /dev/nullcomo arquivo de log, pois não me importo com o registro.

NOTA IMPORTANTE: echoé um comando interno no meu shell, o que significa que é seguro passar senha e token como argumentos para ele. Se fosse um programa externo, alguém poderia ler os argumentos do arquivo /proc. Eu recomendo que você verifique se o comando usado para tubulação está embutido em seu shell. Se você não conseguiu encontrar um integrado adequado, use cat com heredoc:

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

Parte 2

Depois de copiar minha configuração para uma máquina diferente, recebi um erro estranho:

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

Verifiquei se ambos gitsão screenda mesma versão da máquina original e não consegui encontrar a causa raiz. No entanto,este comentário poderiadê uma dica:

getpass() tries too hard to find the real terminal

Como solução alternativa, criei um script separado para GIT_ASKPASS(e sinto que é uma solução mais limpa).

Este é o script principal após as alterações:

#!/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 $@

E isso é 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

Ele lê a senha diretamente do seu TTY e fornece o token descriptografado ao git. Para nome de usuário, apenas ecoa GIT_USERNAME env var.

Também é possível adicionar estas linhas .bashrc(ou qualquer alternativa):

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

E você não precisará do wrapper para comandos.

informação relacionada