我正在尝试使用crontab自动运行git pull命令。我在MacOs机器上。当我在没有cron的情况下使用Git pull,但在使用cron时出现错误时,它运行得很好。我已经尝试了各种解决方案。下面是一些。它们都可以手动工作。
我试着把下面的命令放在脚本automate.sh中,然后用cron运行它。
-
ssh-agent bash -c 'ssh-add /Users/{username}/.ssh/id_rsa; /usr/bin/git pull'
-
eval `ssh-agent -s` && ssh-add ~/.ssh/id_rsa && ssh-add -l && git pull
但我总是低于错误,
fatal: could not read Username for 'https://git.{domain}.com': Device not configured
为什么?
TL;DR:如果可以的话,可以使用ssh URL。(并且:不要从脚本中运行git pull
。)
您在此处显示的URL,来自您的错误消息:
https://git.{domain}.com
不是ssh(安全外壳)URL。它是HTTPS(HTTP over SSL)URL。这是两种完全不同的协议。它们通常在不同的IP端口上运行(22表示ssh,443表示https)。并非所有的Git服务器都对这两种协议都有响应,但如果你的服务器响应了,那么你的Git作为客户端有两个关键区别:
Git作为客户端,通过
https://
连接,必须向服务器提供两项:用户名和密码。(例如,密码不需要是文字密码,因为它可以是PAT。)Git作为客户端,通过
ssh://
连接,必须向服务器提供两项:用户名和某种密钥。
除了";键";vs";密码";,这些看起来——实际上——非常相似,但https和ssh客户端以完全不同的方式获得这两项:
https客户端通常直接从用户键盘读取用户名和密码,绕过所有重定向尝试。
ssh客户端通常将用户名作为参数,并从公钥和/或私钥对文件中读取密钥和/或从代理中获取密钥。
在这两个要点中,这个词通常是在做很多繁重的工作,但这是您看到的错误的原因。当您从cron作业运行git pull
时,没有键盘可供读取。在物理上,cron不可能让您键入用户名和密码,而cron可能在您甚至不在计算机上时运行。在Mac上尝试打开/dev/tty
会导致Device not configured
错误。
得到该错误后,libCURL库1放弃,整个拉取失败。
现在,请注意,ssh从参数获取用户名,而不是通过键入它,并从文件和/或ssh代理获得密钥。因此,ssh在这里已经有了巨大的优势:它不需要你坐在键盘旁,随时准备输入用户名和密码。因此,如果你让Git使用ssh,2,你更有可能继续。
这并不是答案的结束(尽管这是开始,因此也是上面的TL;DR)。使用https时,可以告诉libCURL不要从用户那里读取用户名和密码。如何的具体操作取决于操作系统,但通常情况下,可以使用以下形式的URL:
https://user@host:password/path/to/repo.git
这样做的缺点是,你已经把你的用户名和密码放在明文中,让每个人都能看到。除非是您的专用选项,否则请避免此操作。
或者,Git可以使用凭据助手将用户名和密码提供给libCURL。Git的另一个大秘密是:Git从不进行任何身份验证。如果你想自称是巴拉克·奥巴马,3你可以继续做下去,Git会相信你。
是其他程序进行身份验证。Git依赖于这些其他程序——特别是web服务器和ssh服务器——来进行身份验证;这决定了您可以在其他机器上读取和写入哪些存储库。在您的本地机器上,由本地操作系统的权限决定您可以读取和写入哪些存储库。
由于ssh有自己相当大且复杂的方法来处理身份验证(包括ssh代理),所以我们在这里根本不涉及这一点,但我将稍微谈谈使用libCURL的凭据助手。Git总是有两个简单的store
和cache
:store
助手只需将用户名和密码保存在一个文件中(它不加密,所以要考虑避免这种情况,或者至少要小心保护这个文件)。cache
助手不会永久存储凭据,而只是临时存储,因此危险性较小,但它会被困在某个其他助手前面。另一个助手可能需要密码,为了避免每次都必须在中键入密码,您可以将缓存助手插入其中:如果缓存项已过期,缓存助手将从下一级助手处获得密码,现在您必须键入密码;但除此之外,它会传递回缓存的条目,这样您就不必在这个时间键入它。
用于各种操作系统的Git附带了额外的操作系统特定帮助程序。特别是在OSX上,有一个git-credential-osxkeychain
助手使用OSX Keychain软件。(我不使用这个:我使用ssh。)
有关所有这些的完整解释,请参阅gitcredentials文档。某些特定的帮助程序何时以及是否适用于您的特定https设置取决于太多的因素。
1Git没有内置所有的https协议;相反,Git只是针对libCURL进行链接。您的操作系统的libCURL依赖于操作系统,因此这有助于Git避免过于依赖操作系统。
2当使用ssh URL时,Git实际上也只是运行ssh。
3如果你真的是巴拉克·奥巴马,你为什么要读这篇文章?
关于git pull
git pull
命令做两件事:
首先,它运行或尝试运行
git fetch
。这会连接到其他系统并获得新的提交,或者,在您的情况下,无法连接(然后会停止git pull
)。如果步骤1中一切顺利,
git pull
现在运行第二个Git命令。您可以提前选择是git rebase
还是git merge
。
命令#2旨在以交互方式工作。无论您选择哪个命令,Git都会尽最大努力将您所做的任何工作(在存储库中进行新的提交)与提取步骤中出现的任何新提交(命令#1)结合起来这可能需要用户帮助如果是,命令#2将打印关于需要什么帮助的消息,并以错误状态终止,从而在Git存储库中留下一堆混乱<在你尝试进一步的操作之前,这个烂摊子必须清理干净>
因为我们不知道命令#2是否会成功,所以在无人参与的脚本中使用git pull
总是一个坏主意。我们可以猜测命令#1是否可能成功,并在脚本中检查这一点,因此可以在脚本中使用git fetch
。在任何无人值守脚本中使用git rebase
或git merge
都是不可行的,除非您的脚本检查故障并安排有用的事情发生(提醒人员,停止尝试进一步的命令,等等)。
要在脚本中正确执行所有这些操作,必须将git pull
分解为其组成步骤,因为git pull
的故障可能意味着:
- 获取失败:可能是暂时的网络故障;没什么大不了的;请稍后再试
- 第二步失败了:灾难不要继续
您需要知道发生了哪些情况,因此不能使用git pull
。