Puppet: Shell-Befehl ausführen, wenn Datei (oder Paket) aktualisiert wird

8

Ich möchte mysql_tzinfo_to_sqlimmer dann ausführen, wenn sich das tzinfo- Paket (unter Ubuntu Server) ändert. Ich dachte, Puppet kann sich darum kümmern.

Ich dachte, dass entweder Puppet auf eine Änderung der Paketversion reagieren würde oder, wenn nicht, auf eine Änderung der Zeitstempel einer im Paket enthaltenen Datei.

Die einzige Möglichkeit, dies zu tun, besteht darin, eine Ressource ohne direkte Aktion und eine davon abhängige Exec zu haben.

Die Fragen, die ich habe, sind:

  1. Ist es möglich, eine Datei zu definieren, die nur zum Benachrichtigen einer anderen Ressource (z. B. exec ) verwendet wird?
  2. Ist es möglich, eine Paketressource so zu definieren, dass eine andere Ressource (z. B. exec ) aktiviert wird, wenn sich das Paket ändert oder aktualisiert?
  3. Ist es möglich, eine Exec- Ressource zu definieren , die anstelle eines Befehls aus dem Dateisystem eine Shell-Befehlszeile ausführt (z. B. mit Pipes und Umleitung)?

Alles in allem scheint es überwältigend.

FOLLOWUP : Fantastische Antworten! Der Vollständigkeit halber (und für die Aufzeichnung) sollte ich Folgendes beachten:

  1. Der vollständige Shell-Befehl von Interesse ist mysql_tzinfo_to_sql | mysql -u root -p password (er lädt tzinfo in eine MySQL-Datenbank für die Verwendung mit MySQL).
  2. Die Prüfung von /etc/tzinfowäre zwecklos, da dies lediglich die lokale Zeitzonenkonfiguration ist. Ziel ist es, auf Änderungen in den tzinfo-Daten selbst zu achten (also auf das Beobachten von /usr/share/zoneinfo).
  3. Ebenso wäre der Inhalt falsch anzusehen - da er sich wahrscheinlich nicht ändert; Am besten sehen Sie sich die mtime oder alle an, da sich die Dateizeitzeiten nach jedem tzinfo-Update ändern sollten.

Auch James Turnbull schrieb alles über die Prüfung , wenn es eingeführt wurde. Die Metaparameter-Referenz enthält eine kurze Beschreibung der Funktionsweise des auditParameters.

Mei
quelle
Hat eine der Antworten das Problem tatsächlich gelöst? Wenn ja, könnten Sie akzeptieren, wer es am besten gelöst hat? Ich interessiere mich auch für dieses Problem, und es wäre ein nützlicher Hinweis darauf, was zu verfolgen ist.
Tom Anderson
Ich habe das nie ganz zum Laufen gebracht - ich habe aufgegeben und mache es einfach von Zeit zu Zeit (oder während der Installation) von Hand.
Mei

Antworten:

7

Verwenden Sie das Überwachungsattribut, um den Dateiinhalt oder die Paketversionsnummer zu verfolgen und die Änderung durch Abonnieren der Paketressource auszulösen. Ein paar Probleme damit, dies funktioniert nicht mit --noop, da die Datei state.yaml die Datei md5 Prüfsumme / Paketversion im --noop-Modus aktualisiert. Ich bin mir nicht sicher, ob dies ein ausstehender Fehler ist, da ich ihn momentan nicht finden kann.

file { '/etc/tzinfo':
  audit => content,
}

exec { '/usr/bin/mysql_tzinfo_to_sql':
  subscribe => File['/etc/tzinfo'],
}

Eine zuverlässigere Methode besteht darin, die Datei an anderer Stelle zu duplizieren und zum Auslösen von Aktualisierungen zu verwenden (der Speicherort ist nicht wichtig, wir verfolgen nur das ursprüngliche tzinfo als Quelle).

file { '/etc/puppet/stage/tzinfo':
  source => '/etc/tzinfo',
}

exec { '/usr/bin/mysql_tzinfo_to_sql':
  subscribe => File['/etc/tzinfo'],
}

Die zweite Methode funktioniert natürlich nicht mit Paketen, aber Sie würden die Probleme --noop und state.yaml vermeiden.

In Bezug auf die dritte Frage können Sie Pipe und Redirects verwenden (verwenden Sie einen Titel und fügen Sie den Befehl in das Befehlsattribut ein):

exec { 
  '/bin/echo foo | grep foo > /tmp/foo':
}
Nan Liu
quelle
Dies ist eine fantastische Antwort - obwohl ich nicht daran interessiert bin, die aktuelle Zeitzone zu sehen, sondern Änderungen an den Zeitzonendaten in / usr / share / tzinfo. Die Verwendung von 'audit => all' gegen / usr / share / tzinfo sollte ausreichen, oder?
Mei
Wenn Sie versuchen, das Verzeichnis erneut zu verwenden, funktioniert dies nicht ganz, da die Prüfung nur für den angegebenen Pfad funktioniert und nicht erneut ausgeführt wird. audit => all bedeutet, alle Attribute zu prüfen, nicht alle Dateien. Ich würde die zweite Methode mit Rekurs verwenden, wenn Sie diese Methode wählen.
Nan Liu
Guter Punkt - obwohl ich nicht zurückgreifen wollte. Das Verzeichnis / usr / share / tzinfo sollte sich jedes Mal ändern, wenn das tzdata-Paket aktualisiert wird - zumindest dachte ich das.
Mei
Ich brauchte etwas Ähnliches und versuchte die erste Methode - eine Prüfung einer Datei. In meinem Fall ist die Datei der Commit-Hash eines Git-Checkout aus einem früheren Exec. Die Methode funktioniert, außer dass die Änderung an der Datei erst beim Puppet-Lauf nach demjenigen bemerkt wird, der die Datei ändert.
Thomas Vander Stichele
5

Ja, das sollten Sie können.

* theoretisches Codebeispiel

package{'tzinfo':
  audit  => all,
  notify => Exec['mysql_tzinfo_to_sql'],
}

exec{'mysql_tzinfo_to_sql':
  refreshonly  => true,
  command      => "bash -c '/usr/local/bin/mysql_tzinfo_to_sql >> /var/log/stuff.log'",
}
  1. Ja, über den Benachrichtigungs-Meta-Parameter. Ich bin mir jedoch nicht zu 100% sicher, dass die neue Überwachungsfunktion in Puppet 2.6 eine Benachrichtigung auslöst, wenn sich die Paketversion außerhalb der Kontrolle von Puppet ändert.

  2. Ja, nur mit refresh => true

  3. Ja, siehe mein Beispiel. Puppet führt aus Gründen der Einfachheit und Sicherheit Exec-Befehle außerhalb einer interaktiven Shell aus. Sie können Puppet Bash im Subshell-Modus mit dem Schalter -c verwenden lassen, aber beachten Sie die Anführungszeichen.

Robbyt
quelle
1
Erfrischung ist hier wichtig, denke ich. Der Befehl bash scheint inkongruent zu sein: Wenn dieser Befehl funktioniert, sollte auch ein normaler Shell-Befehl funktionieren, oder? Auf jeden Fall klingt es so.
Mei
Müssen Sie bash -ceine Umleitung durchführen?
Tom Anderson
Ja, bash -cist in diesem Beispiel für die Shell-Umleitung erforderlich. Puppet verwendet keine interaktive Shell für exec.
Robbyt
2

Ich glaube, ich habe es geschafft, das zum Laufen zu bringen. Hier sind die relevanten Teile meines Puppenmanifests:

file { '/usr/share/zoneinfo':
  audit => mtime,
  recurse => true,
  notify => Exec['mysql_tzinfo']
}

exec { 'mysql_tzinfo':
  refreshonly => true,
  command => 'mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql',
}

Nach dem ersten Start wird die Datei mysql_tzinfo exec übersprungen. getestet durch Berühren von / usr / share / zoneinfo / Etc / UTC, wodurch mysql_tzinfo exec aufgefordert wurde, beim nächsten Mal ausgeführt zu werden.

Daniel Vena
quelle
2

Diese Frage ist alt, aber ich bin auf der Suche nach etwas anderem darüber gewandert und wollte eine alternative Antwort zur Prüfung hinzufügen.

Es wird keine Marionette verwendet: Da wir eine RPM-Installation / -Update auslösen möchten, warum nicht einen RPM-Trigger verwenden? Es nutzt genau das System, mit dem die Installation durchgeführt wurde, und erweitert es ordnungsgemäß auf eine Weise, für die es entwickelt wurde.

Das Erstellen der Trigger-Drehzahl ist sehr einfach, und obwohl es keinen Spaß macht, sie zu lernen, kann sie, sobald die erste fertig ist, auch für andere Apps und Bedingungen sehr einfach wiederholt werden - daher sind die Kosten ungleich Null, aber die Vorteile überwiegen schnell und bei weitem Kosten.

Während wir für Puppet hier sind und das Problem mit Puppet lösbar ist, mache ich mir Sorgen, dass ein schwacher Teil eines Tools genutzt wird, um schlecht auf einen Zustand zu reagieren, der mit einem Tool, das sich bereits auf dem Host und einem Tool befindet, viel einfacher auszulösen ist in die die meisten Admins auf der Box ihren Zeh hätten tauchen sollen. Es tut uns leid, eine Lösung außerhalb der Grenzen vorzuschlagen, aber wenn Sie in Zukunft wie ich über diese Nachricht wandern und der RPM-Trigger eine Option für Sie ist, ziehen Sie dies bitte in Betracht.

user2066657
quelle