Cada vez que ejecuto git push
, tengo que escribir mi nombre de usuario y contraseña cuando se me solicite manualmente.
Sin embargo, quiero automatizar este proceso.
Entonces, intenté pasar las credenciales al comando usando tuberías:
printf 'username\npassword' | git push
¡Pero el mensaje de nombre de usuario y contraseña aún no desaparece!
¿Por qué no funciona?
Nota:
Sé que esto se puede hacer usando: pero me interesa saber qué hay de malo con el método de tubería.
git push 'https://username:[email protected]/username/repo.git'
Además, para confirmar que este proceso funciona en otros casos, hice un experimento.
Creé un script b.py
:
b.py
:
#!/usr/bin/env python3
username = input()
password = input()
log = open("log.txt", "w")
print(username + "\n" + password, file=log)
Luego, ejecuté printf 'abcd\nefgh' | ./b.py
en la terminal, lo que funcionó como se esperaba y resultó en el archivo de registro que contiene las cadenas de nombre de usuario y contraseña:
log.txt
:
abcd
efgh
Respuesta1
Esto solo funcionaría en el caso de indicaciones secuenciales que son la parte inmediata del script según su ejemplo. Sin embargo, en el caso de que git
sus valores se pasen al proceso antes de cualquier solicitud de nombre de usuario/contraseña, probablemente mientras hace todo (red, etc.) antes, GIT_ASKPASS
como referencia:
https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables
Respuesta2
Condiciones previas
Hace algún tiempo, GitHub dejó de aceptar contraseñas y pidió a los usuarios que crearan tokens. Por supuesto, no podía recordar el token, pero tampoco quería almacenarlo como texto sin formato en formato .git-credentials
. Además, no quería pasarlo como argumento (¡alguien puede leerlo /proc
o .bash_history
encontrarlo!). Escribí mi cifrador simple para cifrar el token con una contraseña, pero, al igual que usted, no pude canalizar el token descifrado git
y encontré esta pregunta mientras buscaba una solución. Desafortunadamente, no encontré la respuesta aquí. Sin embargo, tuve suerte de encontrar una pregunta no relacionada que me llevó a la respuesta. Y la respuesta esguion.
Solución
Podemos usarlo script
para crear una sesión automatizada y canalizarle credenciales. Este es el guión que he escrito para ello:
#!/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
indica que no quiero que se repitan mis credenciales (impresas en la terminal). Lo estoy usando /dev/null
como archivo de registro ya que no me importa registrar.
NOTA IMPORTANTE: echo
es un comando integrado en mi shell, lo que significa que es seguro pasarle contraseña y token como argumentos. Si fuera un programa externo, alguien podría leer los argumentos de /proc
. Le recomiendo que verifique si el comando que usa para la tubería está integrado en su shell. Si no pudo encontrar una función incorporada adecuada, use cat con heredoc:
token=$(
(
cat <<EOF
$password
EOF
) | decrypt_token
)
Parte 2
Después de copiar mi configuración en una máquina diferente, aparece un error extraño:
fatal: could not read Password for 'https://[email protected]': Success
Verifiqué que ambos git
y screen
tienen la misma versión que en la máquina original y no pude encontrar la causa raíz. Sin embargo,este comentario puededar un consejo:
getpass() tries too hard to find the real terminal
Como solución alternativa, creé un script separado GIT_ASKPASS
(y creo que es una solución más limpia).
Este es el script principal después de los cambios:
#!/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 $@
Y esto es 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
Lee la contraseña directamente desde su TTY y proporciona un token descifrado a git. Para el nombre de usuario simplemente hace eco de la var de entorno GIT_USERNAME.
También es posible agregar estas líneas .bashrc
(o cualquier alternativa):
export TTY=$(tty)
export GIT_USERNAME=username
export GIT_ASKPASS=~/git-creds
Y no necesitarás el contenedor para los comandos.