前提条件

前提条件

を実行するたびに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-内部環境変数

答え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。パイプに使用するコマンドがシェルに組み込まれているかどうかを確認することをお勧めします。適切な組み込みコマンドが見つからない場合は、heredoc 付きの cat を使用します。

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

パート2

セットアップを別のマシンにコピーした後、奇妙なエラーが発生しました:

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

gitとの両方がscreen元のマシンと同じバージョンであることを確認しましたが、根本的な原因は見つかりませんでした。しかし、このコメント 5月ヒントを提供する:

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

また、コマンドのラッパーは必要ありません。

関連情報