git,nagios和钩子,损坏的git repo


14

背景

我们正在使用nagios监视我们的基础架构。目前,我们没有nagios配置受版本控制,我们中有两个人管理nagios配置。因此,我正在努力使我们的nagios配置进入中央git存储库,使用一些钩子进行语法检查,然后如果配置看起来不错,请将其“激活”。我正在用这个家伙的帖子为起点。

我要实现的一般工作流程是:

  1. 编辑nagios配置的本地git回购。添加编辑的文件,在本地提交。
  2. git push origin master 到远程仓库。
  3. 推送被预接收挂钩拦截,该挂钩接收文件,将它们移动到服务器上的临时目录,然后通过nagios语法检查器运行它们。
  4. 如果语法检查器通过,请接受推送,然后使用后提交钩子git pull将新代码插入实时nagios配置目录,然后重新启动nagios。
  5. 如果语法检查器失败,请拒绝该推送,向用户显示nagios语法错误。

但是,当我由于nagios配置中的语法错误而拒绝git push时,我遇到了一种奇怪的行为。我希望发生的事情是,如果我拒绝该挂钩,则尝试进行的推送应该使存储库保持原样,并且保持不变。不过,事实似乎并非如此。以下是我所看到的详细信息:

问题

我在本地编辑nagios配置,故意包括语法错误,添加然后在本地提交:

host:nagios erik$ vi nagios.cfg
host:nagios erik$ git add nagios.cfg
host:nagios erik$ git commit -m "syntax error"
[master da71aed] syntax error
 1 files changed, 1 insertions(+), 0 deletions(-)

现在,我将这些更改推送到主存储库中。由于语法错误,这将被拒绝:

host:nagios erik$ git push origin master
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 12.74 KiB, done.
Total 3 (delta 1), reused 2 (delta 1)
remote: Previous HEAD position was 3ddc880... removed syntax error
remote: HEAD is now at da71aed... syntax error
remote: Nagios Config Check Exit Status: 254
remote: Your configs did not parse correctly, there was an error. Output follows.
remote:
remote: Nagios Core 3.2.3
remote: Copyright (c) 2009-2010 Nagios Core Development Team and Community Contributors
remote: Copyright (c) 1999-2009 Ethan Galstad
remote: Last Modified: 10-03-2010
remote: License: GPL
remote:
remote: Website: http://www.nagios.org
remote: Reading configuration data...
remote: Error in configuration file '/tmp/nagiosworkdir/nagios.cfg' - Line 23 (NULL value)
remote:    Error processing main config file!
remote:
remote:
remote:
remote: ***> One or more problems was encountered while processing the config files...
remote:
remote:      Check your configuration file(s) to ensure that they contain valid
remote:      directives and data defintions.  If you are upgrading from a previous
remote:      version of Nagios, you should be aware that some variables/definitions
remote:      may have been removed or modified in this version.  Make sure to read
remote:      the HTML documentation regarding the config files, as well as the
remote:      'Whats New' section to find out what has changed.
remote:
To git@remote-server.example.com:nagios
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@remote-server.example.com:nagios'

这本应该涉及到远程仓库,但确实如此。如果我转到另一个本地临时目录并尝试克隆该存储库,则会得到:

host:temp erik$ git clone git@remote-server.example.com:nagios
Cloning into nagios...
remote: Counting objects: 30, done.
remote: Compressing objects: 100% (29/29), done.
remote: Total 30 (delta 12), reused 0 (delta 0)
Receiving objects: 100% (30/30), 29.81 KiB, done.
Resolving deltas: 100% (12/12), done.
error: Trying to write ref HEAD with nonexistant object da71aedfde2e0469288acd9e45bb8b57a6e5a7b3
fatal: Cannot update the ref 'HEAD'.

现在,我返回原始工作目录,修复语法错误,添加,提交和推送:

host:nagios erik$ vi nagios.cfg
host:nagios erik$ git add nagios.cfg
host:nagios erik$ git commit -m "removing syntax error, push should succeed this time"
[master f147ded] removing syntax error, push should succeed this time
 1 files changed, 0 insertions(+), 2 deletions(-)
host:nagios erik$ git push origin master
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 487 bytes, done.
Total 4 (delta 2), reused 0 (delta 0)
remote: Previous HEAD position was 4c80d45... syntax error
remote: HEAD is now at f147ded... removing syntax error, push should succeed this time
remote: Nagios Config Check Exit Status: 0
remote: Your configs look good and parsed correctly.
To git@remote-server.example.com:nagios
   3ddc880..f147ded  master -> master

此时,存储库就可以了,我可以更改到临时目录并再次克隆存储库:

host:temp erik$ git clone git@remote-server.example.com:nagios
Cloning into nagios...
remote: Counting objects: 34, done.
remote: Compressing objects: 100% (33/33), done.
remote: Total 34 (delta 14), reused 0 (delta 0)
Receiving objects: 100% (34/34), 30.22 KiB, done.
Resolving deltas: 100% (14/14), done.

这是我正在使用的预接收挂钩。

我在客户端上使用git v1.7.5.4,在服务器上使用v1.7.2.3。

那么,问题来了:当我拒绝推送时,为什么存储库处于不一致状态?我的git钩子有什么问题吗,或者我缺乏对git的理解?


您正在使用什么版本的git?
罗比

@robbyt- 1.7.5.4在客户端上,1.7.2.3在服务器上。
EEAA '02

Answers:


7

你在做:

export GIT_WORK_TREE=/tmp/nagiosworkdir
/usr/bin/git checkout -f $NEW_SHA1

在你的钩子上。尽管它没有触及您的常规工作副本,但它正在更新git-dir中的HEAD引用(特别是引用),如您的错误所示:

...
remote: HEAD is now at da71aed... syntax error
...

您的钩子正在exit 1拒绝更新,但HEAD失败后不会(重新)重置参考。

我认为您需要像这样更新挂钩中的失败分支:

...
if [ "$NAGIOS_CHECK_STATUS" -ne 0 ]
   then
   echo "Your configs did not parse correctly, there was an error. Output follows."
   cat $GIT_WORK_TREE/check.out
   /usr/bin/git reset --hard $OLD_SHA1    # <-- Add This
   exit 1
else
   ...

看起来很刺眼。我今天晚些时候尝试一下。谢谢!
EEAA 2012年

0

git checkout挂钩中的命令正在创建/更新存储库中的HEAD ref。

如果您的存储库是裸存储库,则可以在没有HEAD引用的情况下生存(新克隆将默认检出其master分支,如果有)。只需在退出前删除HEAD ref(也许在,trap这样您就不必安排在每个exit人之前都这样做了)。脚本中“较早”的任何位置:

trap 'git update-ref -m "removing HEAD after temporary checkout to alternate workdir" -d HEAD "$NEW_SHA1"' 0

如果您的存储库不是光秃秃的,或者您想维护一个HEAD ref(以便克隆默认情况下会签出其他分支),那么您将必须保存HEAD ref并在退出前将其还原。

首先,在服务器的存储库中,将HEAD ref重置为指向默认情况下要在新克隆中检出的分支:

git symbolic-ref -m 'setting default branch for new clones' HEAD refs/heads/master

然后,在您的挂钩脚本中(在结帐之前的任何地方):

# Restore HEAD symref when exiting
saved_HEAD=$(git symbolic-ref HEAD)
trap 'git symbolic-ref -m "restoring HEAD after temporary checkout to alternate workdir" HEAD "$saved_HEAD"' 0

顺便说一句,pre-receive钩子应该确保它们完全读入stdin并处理所有输入的行。在消耗所有输入之前退出有时会在此git-receive-pack过程中触发SIGPIPE ;如果您一次只推送一个引用(因为您至少读取了一行),那么在您的情况下可能不会出现这种情况,但这是需要牢记的。将此钩子当作update钩子可能会更容易,因为您只需一次关注一个裁判,就可以单独拒绝每个裁判的推动(也许您只关心保持主控器尖端“干净”;在检查和报告其他分支机构的技巧,但切勿拒绝它们,以便将其用于未完成工作的协作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.