Попробуйте что-то подобное в вашем 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
(примечание: это Makefile, поэтому отступы - это табуляции, а не пробелы. Конечно. Также важно, чтобы после \
строк продолжения не было пробелов - альтернативно избавьтесь от escape-косых черт и сделайте его одним длинным, почти нечитаемая строка)
Этот make
рецепт GNU сначала проверяет, существует ли файл с именем example.gz
(потому что мы собираемся использовать его с -z
in curl
), и создает его с помощью, touch
если это не так. Прикосновение создает его с отметкой времени 00:00 (12:00 текущего дня).
Затем он использует опцию curl
s -z
( --time-cond
) для загрузки, только example.gz
если он был изменен с момента последней загрузки. -z
может быть дано фактическое выражение даты или имя файла. Если задано имя файла, оно будет использовать время модификации файла в качестве условия времени.
После этого, если local.dat
его не существует, он создает его с touch
использованием временной метки, которая гарантированно будет старше, чем у example.gz
. Это необходимо, потому local.dat
что должна существовать следующая команда, чтобы использовать stat
ее метку времени mtime.
Затем, если example.gz
есть отметка времени новее local.dat
, это трубы example.gz
в transmogrify
и перенаправляет вывод local.dat
.
И, наконец, он занимается бухгалтерией и уборкой:
- он усекается
example.gz
(потому что вам нужна только временная метка, а не весь файл)
touch
Если example.gz
у него такая же временная метка, какlocal.dat
Цель .PHONY гарантирует, что local.dat
цель всегда выполняется, даже если файл с таким именем уже существует.
Спасибо @Toby Speight за указание в комментариях, что моя оригинальная версия не будет работать, и почему.
В качестве альтернативы, если вы хотите передать файл напрямую, transmogrify
не загружая его сначала в файловую систему:
.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
ПРИМЕЧАНИЕ: это в основном не проверено, поэтому могут потребоваться некоторые незначительные изменения, чтобы получить правильный синтаксис. Здесь важен метод, а не решение копи-пасты Cargo-Cult.
Я использую варианты этого метода (например, touch
файл временной метки) в make
течение десятилетий. Это работает, и, как правило, позволяет мне избежать написания собственного кода разрешения зависимостей в sh (хотя я должен был сделать что-то подобное stat --printf %Y
здесь).
Все знают, make
что это отличный инструмент для компиляции программного обеспечения ... IMO, он также очень недооцененный инструмент для задач системного администратора и сценариев.
-z
Флаг, конечно, предполагает , что удаленный сервер используетIf-Modified-Since
заголовки. Это не обязательно так. В зависимости от настроек сервера, вам может потребоваться что-то сделатьETag
, либо путем проверкиCache-Control
заголовков, либо путем проверки отдельного файла контрольной суммы (например, если сервер предоставляет asha1sum
).make
, используетcmp
или что-то для сравнения старых и новых файлов, иmv newfile oldfile
если они отличаются) , Кстати, заголовки контроля кэша не сообщают вам, является ли файл более новым, чем заданное время. они говорят вам, как долго администраторы сервера хотят, чтобы вы кешировали определенный файл, и часто используются маркетинговыми дроидами в качестве метода уничтожения кеша для «улучшения» их веб-статистики.ETag
это еще один способ сделать это, как отдельный файл контрольной суммы. Все зависит от того, как настроен сервер. Например, можно получить cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA1SUMS и проверить, изменился ли он, прежде чем принимать решение о получении полного ISO. ETag делает то же самое, используя заголовок вместо отдельного файла (и, похожеIf-Modified-Since
, использует HTTP-сервер, реализующий его).Cache-Control
будет последним средством, за исключением загрузки файла, если другие методы не поддерживаются - это, безусловно, наименее точное, поскольку оно пытается предсказать будущее.ETag
/If-None-Match
и другие контрольные суммы более надежны, чемIf-Modified-Since
тоже. В любом случае, эти комментарии просто пытаются изложить предположения об ответе (а именно, что-z
предполагает поддержку сервера) - базовый метод должен быть довольно легко адаптировать к другим алгоритмам проверки изменений.Другой альтернативой является использование системы сборки, которая использует контрольные суммы зависимостей, чтобы определить, следует ли инициировать перестроения. Я использовал «сенсорный» трюк с Gnu Make, но гораздо проще, когда вы можете указать динамические зависимости и когда файлы, которые не изменяются, не вызывают перестроения. Вот пример использования GoodMake :
источник
-X HEAD
, man-страница curl рекомендует использовать-I
: "(-X) изменяет только фактическое слово, используемое в HTTP-запросе, но не изменяет поведение curl. Так, например, если вы хотите сделать правильный запрос HEAD, используя -X HEAD не будет достаточно. Вам нужно использовать опцию -I, - head. "