在 mac OS 上从 crontab 运行 git pull 命令问题
Posted
技术标签:
【中文标题】在 mac OS 上从 crontab 运行 git pull 命令问题【英文标题】:Issue running git pull command from crontab on mac OS 【发布时间】:2021-12-13 19:58:56 【问题描述】:我正在尝试使用 crontab 自动运行 git pull 命令。我在 MacOs 机器上。 当我在没有 cron 的情况下使用它但使用 cron 时出现错误时,Git pull 工作正常。我已经尝试了各种解决方案。其中一些如下。它们都可以手动正常工作。
我尝试将以下命令放入脚本中自动执行。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
为什么?
【问题讨论】:
【参考方案1】: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://
连接,必须向服务器提供两项:用户名和某种密钥。
除了“key”和“password”之外,这些看起来——实际上——非常相似,但是 https 和 ssh 客户端获得这两个项目的方式完全不同:
https 客户端通常直接从用户的键盘读取用户名和密码,绕过所有重定向的尝试。
ssh 客户端通常将用户名作为参数,并从公钥和/或私钥对文件中读取密钥和/或从代理获取密钥。
这两个要点中的一般这个词做了很多繁重的工作,但这就是您看到错误的原因。当您从 cron 作业运行 git pull
时,没有可供读取的键盘。 cron (它可能在您甚至没有在计算机时运行)在物理上不可能让您输入用户名和密码。在 Mac 上尝试打开 /dev/tty
会导致出现 Device not configured
错误。
得到该错误后,libCURL 库1 放弃,整个拉取失败。
现在,请注意 ssh 从 argument 获取 用户名 - 不是让您输入 - 并获取 keys 来自文件和/或 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 上,有一个使用 OS X Keychain 软件的git-credential-osxkeychain
助手。 (我不使用这个:我使用 ssh。)
有关所有这些的完整说明,请参阅the gitcredentials documentation。某些特定帮助程序何时以及是否适用于您的特定 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 都会尽最大努力将您所做的任何工作结合起来,在您的存储库中进行新的提交,以及在 fetch 步骤中进入的任何新提交(命令 #1) . 这可能需要用户帮助。 如果需要,命令 #2 会打印有关需要哪些帮助的消息,并以错误状态终止,从而在您的 Git 存储库中留下一团糟。 这个烂摊子必须在你尝试进一步操作之前清理干净。
因为我们首先不知道是否命令#2会成功,所以在无人看管的脚本中使用git pull
总是是个坏主意。我们可以猜测命令#1 是否有可能成功,并在脚本中进行检查,因此可以在脚本中使用git fetch
。但是,在任何 无人值守 脚本中使用 git rebase
或 git merge
是绝对不行的,除非您的脚本检查失败并安排一些有用的事情发生(提醒人类,停止尝试进一步的命令,等等)。
要在脚本中正确在中执行所有这些操作,您必须将git pull
分解为其组成步骤,因为git pull
的失败可能意味着: p>
你需要知道发生了哪些,所以你不能使用git pull
。
【讨论】:
以上是关于在 mac OS 上从 crontab 运行 git pull 命令问题的主要内容,如果未能解决你的问题,请参考以下文章
如何在 mac os x 上从通过 USB 连接的多轨混音器获取输入
在 Mac OS X 上从 boot2docker 迁移到 Vagrant+NFS 的最快方法是啥?
如何在 Mac 上从 Dockerfile 运行 bash 脚本