Essayez quelque chose comme ça dans votre 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
(Remarque: il s'agit d'un Makefile, donc les retraits sont des tabulations, pas des espaces. Bien sûr. Il est également important qu'il n'y ait pas d'espaces après les \
lignes de continuation - vous pouvez également vous débarrasser des échappements antislash et en faire un long, ligne presque illisible)
Cette make
recette GNU vérifie d'abord qu'un fichier appelé example.gz
existe (parce que nous allons l'utiliser avec -z
in curl
), et le crée avec touch
si ce n'est pas le cas. Le toucher le crée avec un horodatage de 00h00 (12h00 du jour actuel).
Ensuite, il utilise curl
l' option 's -z
( --time-cond
) pour télécharger uniquementexample.gz
s'il a été modifié depuis le dernier téléchargement. -z
peut recevoir une expression de date réelle ou un nom de fichier. Si on lui donne un nom de fichier, il utilisera l'heure de modification du fichier comme condition temporelle.
Après cela, s'il local.dat
n'existe pas, il le crée avec touch
, en utilisant un horodatage garanti comme étant plus ancien que celui de example.gz
. Ceci est nécessaire car local.dat
doit exister pour que la prochaine commande puisse être utiliséestat
pour obtenir son horodatage mtime.
Ensuite, si example.gz
a un horodatage plus récent que local.dat
, il les tuyaux example.gz
dans transmogrify
et réoriente la sortielocal.dat
.
Enfin, il fait la comptabilité et le nettoyage:
- il tronque
example.gz
(car il vous suffit de garder un horodatage, et non tout le fichier)
touch
es example.gz
pour qu'il ait le même horodatage quelocal.dat
La cible .PHONY garantit que la local.dat
cible est toujours exécutée, même si le fichier de ce nom existe déjà.
Merci à @Toby Speight d'avoir souligné dans les commentaires que ma version originale ne fonctionnerait pas, et pourquoi.
Alternativement, si vous souhaitez diriger le fichier directement transmogrify
sans le télécharger d'abord dans le système de fichiers:
.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
REMARQUE: ceci n'est généralement pas testé et peut nécessiter quelques modifications mineures pour obtenir la syntaxe exactement correcte. L'important ici est la méthode, pas une solution culte du copier-coller.
J'utilise des variantes de cette méthode (c'est-à-dire touch
un fichier d'horodatage) avec make
depuis des décennies. Cela fonctionne et me permet généralement d'éviter d'avoir à écrire mon propre code de résolution de dépendance dans sh (même si j'ai dû faire quelque chose de similaire avecstat --printf %Y
ici).
Tout le monde sait que make
c'est un excellent outil pour compiler des logiciels ... IMO c'est aussi un outil très sous-évalué pour les tâches d'administration système et de script.
-z
drapeau, bien sûr, suppose que le serveur distant utilise des en-If-Modified-Since
têtes. Ce n'est pas nécessairement le cas. Selon la configuration du serveur, vous devrez peut-être plutôt faire quelque chose avecETag
, ou en vérifiant les en-Cache-Control
têtes, ou en vérifiant un fichier de somme de contrôle distinct (par exemple, si le serveur fournit unsha1sum
).make
, utilisecmp
ou quelque chose pour comparer les anciens et les nouveaux fichiers, etmv newfile oldfile
s'ils sont différents) . BTW, les en-têtes de contrôle du cache ne vous disent pas si le fichier est plus récent qu'une heure donnée. ils vous indiquent pendant combien de temps les administrateurs du serveur veulent que vous mettiez en cache un fichier donné - et sont souvent utilisés par les droïdes marketing comme une pratique de contournement du cache pour "améliorer" leurs statistiques Web.ETag
est une autre façon de le faire, tout comme un fichier de somme de contrôle distinct. Tout dépend de la configuration du serveur. Par exemple, on peut récupérer cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA1SUMS et vérifier s'il a changé avant de décider de récupérer l'ISO complet. ETag fait la même chose, en utilisant un en-tête au lieu d'un fichier séparé (et, commeIf-Modified-Since
, s'appuie sur le serveur HTTP qui l'implémente).Cache-Control
serait une option de dernier recours avant de télécharger le fichier si aucune autre méthode n'est prise en charge - c'est certainement la moins précise car elle essaie de prédire l'avenir.ETag
/If-None-Match
et d'autres sommes de contrôle sont plus fiables queIf-Modified-Since
, aussi. Dans tous les cas, ces commentaires tentent simplement de présenter les hypothèses de la réponse (à savoir, qui-z
suppose la prise en charge du serveur) - la méthode de base devrait être assez facile à adapter à d'autres algorithmes de vérification des modifications.Une autre alternative consiste à utiliser un système de génération qui utilise des sommes de contrôle de dépendance pour déterminer s'il faut déclencher des reconstructions. J'ai beaucoup utilisé le "toucher" avec Gnu Make, mais c'est beaucoup plus simple lorsque vous pouvez spécifier des dépendances dynamiques et que les fichiers qui ne changent pas ne déclenchent pas de reconstructions. Voici un exemple d'utilisation de GoodMake :
la source
-X HEAD
, la page de manuel de curl recommande d'utiliser-I
: "(-X) ne modifie que le mot réel utilisé dans la requête HTTP, il ne modifie pas le comportement de curl. Par exemple, si vous souhaitez effectuer une requête HEAD appropriée, utilisez -X HEAD ne suffira pas. Vous devez utiliser l'option -I, - head. "