git、nagios、およびフック、破損したgitリポジトリ


14

バックグラウンド

nagiosを使用してインフラストラクチャを監視しています。現在、バージョン管理下にnagiosの設定はありません。nagiosの設定を管理するのは2人です。そのため、私はnagiosの設定を中央のgitリポジトリに取り込み、構文チェックを行うためにいくつかのフックを使用し、設定が適切に見える場合は「アクティブ」にします。この男の投稿を出発点として使用しています。

私が実装しようとしている一般的なワークフローは次のとおりです。

  1. nagios configのローカルgitリポジトリを編集します。編集したファイルを追加し、ローカルでコミットします。
  2. git push origin master リモートリポジトリへ。
  3. プッシュはpre-receiveフックによってインターセプトされます。pre-receiveフックはファイルを取得し、サーバー上の一時ディレクトリに移動し、nagios構文チェッカーを介して実行します。
  4. 構文チェッカーが合格した場合、プッシュを受け入れ、git pull新しいコードへのpost-commitフックを使用して、ライブnagios構成ディレクトリに移動し、nagiosを再起動します。
  5. 構文チェッカーが失敗した場合、プッシュを拒否し、ユーザーにnagios構文エラーを表示します。

ただし、nagios configの構文エラーが原因で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.

これが私が使用しているpre-receiveフックです。

クライアントではgit v1.7.5.4を使用し、サーバーではv1.7.2.3を使用しています。

それでは、質問に対して、プッシュを拒否するとリポジトリが一貫性のない状態のままになるのはなぜですか?gitフックに何か問題があるのでしょうか、それともgitの理解が足りないのでしょうか?


どのバージョンのgitを使用していますか?
-robbyt

@robbyt- 1.7.5.4クライアント1.7.2.3上、サーバー上。
EEAA

回答:


7

あなたはやっている:

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

あなたのフックに。通常の作業コピーに影響しませんHEADが、エラーに示されているように、git-dirの参照(具体的には参照)を更新しています。

...
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

0

git checkoutフック内のコマンドは、リポジトリ内のHEAD refを作成/更新しています。

リポジトリがむき出しのリポジトリである場合、HEAD refなしで存続できます(新しいクローンは、デフォルトで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がトリガーされることがあります。一度に1つのrefのみをプッシュする場合(少なくとも1行を読むため)、これはおそらくあなたのケースには現れませんが、心に留めておくべきことです。おそらく、このフックupdateを一度に1つのrefだけに関係する必要があるフックとして行う方が簡単で、各refのプッシュを個別に拒否できます(おそらく、マスターの先端を「クリーン」に保つことだけを気にします。他のブランチのヒントについて報告しますが、それらを拒否しないでください。そうすれば、それらは不完全な作業のコラボレーションに使用できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.