Всякий раз, когда я запускаю 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
И вам не понадобится оболочка для команд.