Versuchen Sie so etwas in Ihrem Makefile:
.PHONY: local.dat
local.dat:
[ -e example.gz ] || touch -d '00:00' example.gz
curl -z example.gz -s http://example.org/example.gz -o example.gz
[ -e $@ ] || touch -d 'yesterday 00:00' $@
if [ "$(shell stat --printf '%Y' example.gz)" \
-gt "$(shell stat --printf '%Y' $@)" ] ; then \
zcat example.gz | transmogrify >$@ ; \
fi
truncate -s 0 example.gz
touch -r $@ example.gz
(Hinweis: Dies ist ein Makefile, daher sind die Einrückungen Tabulatoren und keine Leerzeichen. Es ist auch wichtig, dass nach \
den Fortsetzungszeilen keine Leerzeichen mehr vorhanden sind. Alternativ können Sie die Backslash-Escapezeichen entfernen und es lang machen. fast unlesbare Zeile)
Dieses GNU- make
Rezept überprüft zunächst, ob eine aufgerufene Datei example.gz
vorhanden ist (da wir sie mit -z
in verwenden werden curl
), und erstellt sie mit, touch
wenn dies nicht der Fall ist. Die Berührung erstellt es mit einem Zeitstempel von 00:00 (12 Uhr des aktuellen Tages).
Dann verwendet es curl
‚s -z
( --time-cond
) Option , um nur herunterladen , example.gz
wenn es seit dem letzten Mal geändert wurde es heruntergeladen wurde. -z
kann ein tatsächlicher Datumsausdruck oder ein Dateiname angegeben werden. Wenn ein Dateiname angegeben wird, wird die Änderungszeit der Datei als Zeitbedingung verwendet.
Wenn local.dat
dies nicht der Fall ist, wird es anschließend mit touch
einem Zeitstempel erstellt, der garantiert älter als der von ist example.gz
. Dies ist erforderlich, da local.dat
der nächste Befehl vorhanden sein muss stat
, um seinen Zeitstempel mtime abzurufen.
Wenn dann example.gz
hat einen Zeitstempel neuer ist als local.dat
es Leitungen example.gz
in transmogrify
und leitet die Ausgabe zu local.dat
.
Schließlich erledigt es die Buchhaltung und Bereinigung:
- es wird abgeschnitten
example.gz
(weil Sie nur einen Zeitstempel und nicht die gesamte Datei behalten müssen)
touch
es example.gz
so, dass es den gleichen Zeitstempel wie hatlocal.dat
Das .PHONY-Ziel stellt sicher, dass das local.dat
Ziel immer ausgeführt wird, auch wenn die Datei mit diesem Namen bereits vorhanden ist.
Vielen Dank an @Toby Speight für den Hinweis in den Kommentaren, dass meine Originalversion nicht funktionieren würde und warum.
Alternativ, wenn Sie die Datei direkt transmogrify
weiterleiten möchten, ohne sie zuerst in das Dateisystem herunterzuladen:
.PHONY: local.dat
local.dat:
[ -e example.gz ] || touch -d '00:00' example.gz
[ -e $@ ] || touch -d 'yesterday 00:00' $@
if [ "$(shell stat --printf '%Y' example.gz)" \
-gt "$(shell stat --printf '%Y' $@)" ] ; then \
curl -z example.gz -s http://example.org/example.gz | transmogrify >$@ ; \
fi
touch -r $@ example.gz
HINWEIS: Dies ist größtenteils ungetestet und erfordert möglicherweise einige geringfügige Änderungen, um die Syntax genau richtig zu machen. Das Wichtigste dabei ist die Methode, keine Copy-Paste-Cargo-Kult-Lösung.
Ich verwende seit Jahrzehnten Variationen dieser Methode (dh touch
eine Zeitstempeldatei) mit make
. Es funktioniert und ermöglicht mir normalerweise zu vermeiden, dass ich meinen eigenen Code für die Auflösung von Abhängigkeiten in sh schreiben muss (obwohl ich stat --printf %Y
hier etwas Ähnliches tun musste ).
Jeder weiß, dass make
es ein großartiges Tool zum Kompilieren von Software ist ... IMO ist es auch ein sehr unterbewertetes Tool für Systemadministrations- und Skriptaufgaben.
-z
Flag setzt natürlich voraus, dass der Remote-ServerIf-Modified-Since
Header verwendet. Dies muss nicht unbedingt der Fall sein. Abhängig von der Serverkonfiguration müssen Sie möglicherweise stattdessen etwas tunETag
, indem SieCache-Control
Header überprüfen oder eine separate Prüfsummendatei überprüfen (z. B. wenn der Server eine bereitstelltsha1sum
).make
, verwendetcmp
oder etwas anderes, undmv newfile oldfile
wenn sie unterschiedlich sind). . Übrigens sagen Cache-Control-Header nicht, ob die Datei neuer als eine bestimmte Zeit ist. Sie geben an, wie lange die Serveradministratoren möchten, dass Sie eine bestimmte Datei zwischenspeichern - und werden häufig von Marketing-Droiden als Cache-Busting-Methode verwendet, um ihre Webstatistiken zu "verbessern".ETag
ist eine andere Möglichkeit, ebenso wie eine separate Prüfsummendatei. Es hängt alles davon ab, wie der Server eingerichtet ist. Beispielsweise kann man cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA1SUMS abrufen und prüfen, ob es sich geändert hat, bevor man sich entscheidet, die vollständige ISO abzurufen. ETag macht dasselbe, indem es einen Header anstelle einer separaten Datei verwendet (und sich daraufIf-Modified-Since
verlässt, dass der HTTP-Server ihn implementiert).Cache-Control
Dies wäre ein letzter Ausweg, wenn die Datei nicht heruntergeladen würde, wenn keine anderen Methoden unterstützt würden. Dies ist sicherlich die ungenaueste Option, da sie versucht, die Zukunft vorherzusagen.ETag
/If-None-Match
und andere Prüfsummen zuverlässiger alsIf-Modified-Since
auch. In jedem Fall versuchen diese Kommentare nur, die Annahmen der Antwort darzulegen (nämlich die-z
Serverunterstützung) - die grundlegende Methode sollte relativ einfach an andere Änderungsprüfungsalgorithmen anzupassen sein.Eine andere Alternative besteht darin, ein Build-System zu verwenden, das Abhängigkeitsprüfsummen verwendet, um zu bestimmen, ob Neuerstellungen ausgelöst werden sollen. Ich habe den "Touch" -Trick mit Gnu Make viel verwendet, aber es ist viel einfacher, wenn Sie dynamische Abhängigkeiten angeben können und wenn Dateien, die sich nicht ändern, keine Neuerstellungen auslösen. Hier ist ein Beispiel mit GoodMake :
quelle
-X HEAD
empfiehlt die Manpage von curl die Verwendung von-I
: "(-X) ändert nur das tatsächlich in der HTTP-Anforderung verwendete Wort, ändert jedoch nicht das Verhalten von curl. Wenn Sie beispielsweise eine ordnungsgemäße HEAD-Anforderung mit -X HEAD erstellen möchten wird nicht ausreichen. Sie müssen die Option -I, - head verwenden. "