Предпосылки

Предпосылки

Всякий раз, когда я запускаю 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— встроенная команда в моей оболочке, что означает, что можно безопасно передавать ей пароль и токен в качестве аргументов. Если бы это была внешняя программа, кто-то мог бы прочитать аргументы из /proc. Я рекомендую вам проверить, встроена ли команда, которую вы используете для конвейеризации, в вашу оболочку. Если вы не смогли найти подходящую встроенную, используйте cat с heredoc:

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

Часть 2

После копирования моих настроек на другой компьютер у меня возникла странная ошибка:

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

Я проверил, что обе gitверсии screenсовпадают с версией на оригинальной машине, но не смог найти первопричину. Однако,этот комментарий можетдайте совет:

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

И вам не понадобится оболочка для команд.

Связанный контент