Wypróbuj coś takiego w swoim 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
(uwaga: jest to plik Makefile, więc wcięcia są tabulatorami, a nie spacjami. oczywiście. Ważne jest również to, że po \
liniach kontynuacji nie ma spacji - alternatywnie pozbyć się odwrotnych ukośników i uczynić go jednym długim, prawie nieczytelna linia)
Ten make
przepis GNU najpierw sprawdza, czy plik o nazwie example.gz
istnieje (ponieważ będziemy go używać z -z
in curl
), i tworzy go, touch
jeśli nie ma. Dotyk tworzy go ze znacznikiem czasu 00:00 (12 rano bieżącego dnia).
Następnie używa opcji curl
s -z
( --time-cond
), aby pobrać tylko, example.gz
jeśli został zmodyfikowany od czasu ostatniego pobrania. -z
może otrzymać rzeczywiste wyrażenie daty lub nazwę pliku. Jeśli podano nazwę pliku, wykorzysta czas modyfikacji pliku jako warunek czasowy.
Następnie, jeśli local.dat
nie istnieje, tworzy go za touch
pomocą znacznika czasu, który ma być starszy niż example.gz
. Jest to konieczne, ponieważ local.dat
musi istnieć, aby następne polecenie stat
mogło uzyskać znacznik czasu mtime.
Następnie, jeśli example.gz
jest nowsza niż datownik local.dat
, to rury example.gz
na język transmogrify
i przekierowuje dane wyjściowe local.dat
.
Wreszcie zajmuje się księgowością i porządkami:
- obcina się
example.gz
(ponieważ wystarczy zachować znacznik czasu, a nie cały plik)
touch
es, example.gz
aby miał ten sam znacznik czasu colocal.dat
Cel .PHONY zapewnia, że local.dat
cel jest zawsze wykonywany, nawet jeśli plik o tej nazwie już istnieje.
Dzięki @Toby Speight za wskazanie w komentarzach, że moja oryginalna wersja nie działa i dlaczego.
Alternatywnie, jeśli chcesz bezpośrednio potokować plik transmogrify
bez pobierania go najpierw do systemu plików:
.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
UWAGA: jest to w większości niesprawdzone, więc może wymagać drobnych zmian, aby uzyskać prawidłową składnię. Ważną rzeczą jest tutaj metoda, a nie rozwiązanie kultu ładunku.
Od dziesięcioleci używam odmian tej metody (tj. touch
-Plikowanie pliku znacznika czasu) make
. Działa i zwykle pozwala mi uniknąć pisania własnego kodu rozwiązywania zależności w sh (chociaż musiałem tutaj zrobić coś podobnego stat --printf %Y
).
Wszyscy wiedzą, że make
jest doskonałym narzędziem do kompilowania oprogramowania ... IMO jest również bardzo niedocenianym narzędziem do administrowania systemem i zadań skryptowych.
-z
Flaga, oczywiście, zakłada, że zdalny serwer używaIf-Modified-Since
nagłówków. To niekoniecznie musi tak być. W zależności od konfiguracji serwera może być konieczne zrobienie czegośETag
, sprawdzenieCache-Control
nagłówków lub sprawdzenie oddzielnego pliku sumy kontrolnej (np. Jeśli serwer udostępnia asha1sum
).make
, użyćcmp
lub coś do porównania starych i nowych plików, amv newfile oldfile
jeśli są różne) . BTW, nagłówki kontroli pamięci podręcznej nie mówią, czy plik jest nowszy niż określony czas. informują o tym, jak długo administratorzy serwera chcą buforować dany plik - i są często używane przez droidy marketingowe jako praktyka pomijania pamięci podręcznej w celu „poprawy” ich statystyk internetowych.ETag
jest innym sposobem na zrobienie tego, podobnie jak oddzielny plik sumy kontrolnej. Wszystko zależy od konfiguracji serwera. Na przykład można pobrać cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA1SUMS i sprawdzić, czy zmieniło się przed podjęciem decyzji o pobraniu pełnego ISO. ETag robi to samo, używając nagłówka zamiast osobnego pliku (i, podobnie jakIf-Modified-Since
, polega na implementacji go przez serwer HTTP).Cache-Control
byłoby ostatnią opcją bez pobierania pliku, jeśli nie są obsługiwane żadne inne metody - jest to z pewnością najmniej dokładne, ponieważ próbuje przewidzieć przyszłość.ETag
/If-None-Match
i inne sumy kontrolne są również bardziej niezawodneIf-Modified-Since
. W każdym razie w tych komentarzach po prostu próbuje się określić założenia odpowiedzi (a mianowicie, że-z
zakłada obsługę serwera) - podstawowa metoda powinna być dość łatwa do dostosowania do innych algorytmów sprawdzania zmian.Inną alternatywą jest użycie systemu kompilacji, który używa sum kontrolnych zależności w celu ustalenia, czy wyzwalać przebudowy. Użyłem sztuczki „dotykowej” w Gnu Make dużo, ale jest o wiele prostsze, kiedy można określić zależności dynamiczne i gdy pliki, które się nie zmieniają, nie powodują przebudowy. Oto przykład użycia GoodMake :
źródło
-X HEAD
curl zaleca się użycie-I
: „(-X) zmienia tylko rzeczywiste słowo użyte w żądaniu HTTP, nie zmienia to sposobu, w jaki zachowuje się curl. Na przykład jeśli chcesz wykonać prawidłowe żądanie HEAD, używając -X HEAD nie wystarczy. Musisz użyć opcji -I, - head. ”